Failed Conditions
Pull Request — develop (#3348)
by Sergei
65:23
created

AbstractSchemaManager::removeDoctrineTypeFromComment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

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

234
        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...
235
    }
236
237
    /**
238
     * Lists the tables for this connection.
239
     *
240
     * @return Table[]
241
     */
242
    public function listTables() : array
243
    {
244
        $tableNames = $this->listTableNames();
245
246
        $tables = [];
247
        foreach ($tableNames as $tableName) {
248
            $tables[] = $this->listTableDetails($tableName);
249
        }
250 4101
251
        return $tables;
252 4101
    }
253
254 4101
    public function listTableDetails(string $tableName) : Table
255 4101
    {
256 4057
        $columns     = $this->listTableColumns($tableName);
257
        $foreignKeys = [];
258
259 4101
        if ($this->_platform->supportsForeignKeyConstraints()) {
260
            $foreignKeys = $this->listTableForeignKeys($tableName);
261
        }
262
263
        $indexes = $this->listTableIndexes($tableName);
264
265
        return new Table($tableName, $columns, $indexes, [], $foreignKeys, []);
266
    }
267 4218
268
    /**
269 4218
     * Lists the views this connection has.
270 4218
     *
271
     * @return View[]
272 4218
     */
273 4069
    public function listViews() : array
274
    {
275
        $database = $this->_conn->getDatabase();
276 4218
        $sql      = $this->_platform->getListViewsSQL($database);
277
        $views    = $this->_conn->fetchAll($sql);
278 4218
279
        return $this->_getPortableViewsList($views);
280
    }
281
282
    /**
283
     * Lists the foreign keys for the given table.
284
     *
285
     * @param string $table The name of the table.
286 3062
     *
287
     * @return ForeignKeyConstraint[]
288 3062
     */
289 3062
    public function listTableForeignKeys(string $table, ?string $database = null) : array
290 3062
    {
291
        if ($database === null) {
292 3062
            $database = $this->_conn->getDatabase();
293
        }
294
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);
295
        $tableForeignKeys = $this->_conn->fetchAll($sql);
296
297
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
298
    }
299
300
    /* drop*() Methods */
301
302
    /**
303 4109
     * Drops a database.
304
     *
305 4109
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
306 4109
     *
307
     * @param string $database The name of the database to drop.
308 4109
     */
309 4109
    public function dropDatabase(string $database) : void
310
    {
311 4109
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
312
    }
313
314
    /**
315
     * Drops the given table.
316
     *
317
     * @param string $tableName The name of the table to drop.
318
     */
319
    public function dropTable(string $tableName) : void
320
    {
321
        $this->_execSql($this->_platform->getDropTableSQL($tableName));
322
    }
323
324
    /**
325 4882
     * Drops the index from the given table.
326
     *
327 4882
     * @param Index|string $index The name of the index.
328 4331
     * @param Table|string $table The name of the table.
329
     */
330
    public function dropIndex($index, $table) : void
331
    {
332
        if ($index instanceof Index) {
333
            $index = $index->getQuotedName($this->_platform);
334
        }
335
336
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
337 5159
    }
338
339 5159
    /**
340 5087
     * Drops the constraint from the given table.
341
     *
342
     * @param Table|string $table The name of the table.
343
     */
344
    public function dropConstraint(Constraint $constraint, $table) : void
345
    {
346
        $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
347
    }
348
349
    /**
350 3182
     * Drops a foreign key from a table.
351
     *
352 3182
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
353
     * @param Table|string                $table      The name of the table with the foreign key.
354
     */
355
    public function dropForeignKey($foreignKey, $table) : void
356 3182
    {
357 3182
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
358
    }
359
360
    /**
361
     * Drops a sequence with a given name.
362
     *
363
     * @param string $name The name of the sequence to drop.
364
     */
365
    public function dropSequence(string $name) : void
366
    {
367
        $this->_execSql($this->_platform->getDropSequenceSQL($name));
368
    }
369
370
    /**
371
     * Drops a view.
372
     *
373
     * @param string $name The name of the view.
374
     */
375
    public function dropView(string $name) : void
376
    {
377
        $this->_execSql($this->_platform->getDropViewSQL($name));
378
    }
379
380
    /* create*() Methods */
381
382
    /**
383
     * Creates a new database.
384
     *
385
     * @param string $database The name of the database to create.
386
     */
387
    public function createDatabase(string $database) : void
388
    {
389
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
390
    }
391 1165
392
    /**
393 1165
     * Creates a new table.
394
     */
395
    public function createTable(Table $table) : void
396
    {
397
        $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
398
        $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
399
    }
400
401
    /**
402
     * Creates a new sequence.
403 3228
     *
404
     * @throws ConnectionException If something fails at database level.
405 3228
     */
406
    public function createSequence(Sequence $sequence) : void
407
    {
408
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
409
    }
410
411
    /**
412
     * Creates a constraint on a table.
413
     *
414
     * @param Table|string $table
415
     */
416
    public function createConstraint(Constraint $constraint, $table) : void
417 4880
    {
418
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
419 4880
    }
420 4880
421
    /**
422
     * Creates a new index on a table.
423
     *
424
     * @param Table|string $table The name of the table on which the index is to be created.
425
     */
426
    public function createIndex(Index $index, $table) : void
427 5177
    {
428
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
429 5177
    }
430 5177
431 5156
    /**
432
     * Creates a new foreign key.
433
     *
434
     * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
435
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
436
     */
437
    public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
438
    {
439
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
440
    }
441
442 1167
    /**
443
     * Creates a new view.
444 1167
     */
445 1167
    public function createView(View $view) : void
446
    {
447
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
448
    }
449
450
    /* dropAndCreate*() Methods */
451
452
    /**
453
     * Drops and creates a constraint.
454 1
     *
455
     * @see dropConstraint()
456 1
     * @see createConstraint()
457 1
     *
458
     * @param Table|string $table
459
     */
460
    public function dropAndCreateConstraint(Constraint $constraint, $table) : void
461
    {
462
        $this->tryMethod('dropConstraint', $constraint, $table);
463
        $this->createConstraint($constraint, $table);
464
    }
465
466 3182
    /**
467
     * Drops and creates a new index on a table.
468 3182
     *
469 3182
     * @param Table|string $table The name of the table on which the index is to be created.
470
     */
471
    public function dropAndCreateIndex(Index $index, $table) : void
472
    {
473
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
474
        $this->createIndex($index, $table);
475
    }
476
477
    /**
478
     * Drops and creates a new foreign key.
479 3193
     *
480
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
481 3193
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
482 3193
     */
483
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
484
    {
485
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
486
        $this->createForeignKey($foreignKey, $table);
487
    }
488
489 3228
    /**
490
     * Drops and create a new sequence.
491 3228
     *
492 3228
     * @throws ConnectionException If something fails at database level.
493
     */
494
    public function dropAndCreateSequence(Sequence $sequence) : void
495
    {
496
        $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
497
        $this->createSequence($sequence);
498
    }
499
500
    /**
501
     * Drops and creates a new table.
502
     */
503
    public function dropAndCreateTable(Table $table) : void
504
    {
505
        $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
506
        $this->createTable($table);
507
    }
508
509
    /**
510
     * Drops and creates a new database.
511
     *
512
     * @param string $database The name of the database to create.
513
     */
514
    public function dropAndCreateDatabase(string $database) : void
515
    {
516
        $this->tryMethod('dropDatabase', $database);
517
        $this->createDatabase($database);
518
    }
519 3182
520
    /**
521 3182
     * Drops and creates a new view.
522 3182
     */
523 3182
    public function dropAndCreateView(View $view) : void
524
    {
525
        $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
526
        $this->createView($view);
527
    }
528
529
    /* alterTable() Methods */
530
531
    /**
532
     * Alters an existing tables schema.
533
     */
534
    public function alterTable(TableDiff $tableDiff) : void
535
    {
536
        $queries = $this->_platform->getAlterTableSQL($tableDiff);
537
538
        if (! is_array($queries) || ! count($queries)) {
539
            return;
540
        }
541
542
        foreach ($queries as $ddlQuery) {
543
            $this->_execSql($ddlQuery);
544
        }
545
    }
546 1165
547
    /**
548 1165
     * Renames a given table to another name.
549 1165
     *
550 1165
     * @param string $name    The current name of the table.
551
     * @param string $newName The new name of the table.
552
     */
553
    public function renameTable(string $name, string $newName) : void
554
    {
555
        $tableDiff          = new TableDiff($name);
556
        $tableDiff->newName = $newName;
557 5120
        $this->alterTable($tableDiff);
558
    }
559 5120
560 5120
    /**
561 5120
     * Methods for filtering return values of list*() methods to convert
562
     * the native DBMS data definition to a portable Doctrine definition
563
     */
564
565
    /**
566
     * @param mixed[] $databases
567
     *
568
     * @return string[]
569
     */
570 5025
    protected function _getPortableDatabasesList(array $databases) : array
571
    {
572 5025
        $list = [];
573 5025
        foreach ($databases as $value) {
574 5025
            $value = $this->_getPortableDatabaseDefinition($value);
575
576
            if (! $value) {
577
                continue;
578
            }
579
580
            $list[] = $value;
581 3228
        }
582
583 3228
        return $list;
584 3228
    }
585 3228
586
    /**
587
     * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
588
     *
589
     * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition.
590
     *
591
     * @return string[]
592
     */
593
    protected function getPortableNamespacesList(array $namespaces) : array
594 3892
    {
595
        $namespacesList = [];
596 3892
597
        foreach ($namespaces as $namespace) {
598 3892
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
599 1582
        }
600
601
        return $namespacesList;
602 3892
    }
603 3892
604
    /**
605 3892
     * @param mixed $database
606
     *
607
     * @return mixed
608
     */
609
    protected function _getPortableDatabaseDefinition($database)
610
    {
611
        return $database;
612
    }
613
614
    /**
615 1
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
616
     *
617 1
     * @param mixed[] $namespace The native DBMS namespace definition.
618 1
     *
619 1
     * @return mixed
620 1
     */
621
    protected function getPortableNamespaceDefinition(array $namespace)
622
    {
623
        return $namespace;
624
    }
625
626
    /**
627
     * @param mixed[][] $functions
628
     *
629
     * @return mixed[][]
630
     */
631
    protected function _getPortableFunctionsList(array $functions) : array
632 3156
    {
633
        $list = [];
634 3156
        foreach ($functions as $value) {
635 3156
            $value = $this->_getPortableFunctionDefinition($value);
636 3156
637
            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...
638 3156
                continue;
639
            }
640
641
            $list[] = $value;
642 3156
        }
643
644
        return $list;
645 3156
    }
646
647
    /**
648
     * @param mixed[] $function
649
     *
650
     * @return mixed
651
     */
652
    protected function _getPortableFunctionDefinition(array $function)
653
    {
654
        return $function;
655 1139
    }
656
657 1139
    /**
658
     * @param mixed[][] $triggers
659 1139
     *
660 1139
     * @return mixed[][]
661
     */
662
    protected function _getPortableTriggersList(array $triggers) : array
663 1139
    {
664
        $list = [];
665
        foreach ($triggers as $value) {
666
            $value = $this->_getPortableTriggerDefinition($value);
667
668
            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...
669
                continue;
670
            }
671
672
            $list[] = $value;
673
        }
674
675
        return $list;
676
    }
677
678
    /**
679
     * @param mixed[] $trigger
680
     *
681
     * @return mixed
682
     */
683
    protected function _getPortableTriggerDefinition(array $trigger)
684
    {
685
        return $trigger;
686
    }
687
688
    /**
689
     * @param mixed[][] $sequences
690
     *
691
     * @return Sequence[]
692
     */
693
    protected function _getPortableSequencesList(array $sequences) : array
694
    {
695
        $list = [];
696
697
        foreach ($sequences as $value) {
698
            $list[] = $this->_getPortableSequenceDefinition($value);
699
        }
700
701
        return $list;
702
    }
703
704
    /**
705
     * @param mixed[] $sequence
706
     *
707
     * @throws DBALException
708
     */
709
    protected function _getPortableSequenceDefinition(array $sequence) : Sequence
710
    {
711
        throw DBALException::notSupported('Sequences');
712
    }
713
714
    /**
715
     * Independent of the database the keys of the column list result are lowercased.
716
     *
717
     * The name of the created column instance however is kept in its case.
718
     *
719
     * @param string    $table        The name of the table.
720
     * @param mixed[][] $tableColumns
721
     *
722
     * @return Column[]
723
     */
724
    protected function _getPortableTableColumnList(string $table, ?string $database, array $tableColumns) : array
725
    {
726
        $eventManager = $this->_platform->getEventManager();
727
728
        $list = [];
729
        foreach ($tableColumns as $tableColumn) {
730
            $column           = null;
731
            $defaultPrevented = false;
732
733
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
734
                $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
735
                $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
736
737
                $defaultPrevented = $eventArgs->isDefaultPrevented();
738
                $column           = $eventArgs->getColumn();
739
            }
740
741
            if (! $defaultPrevented) {
742
                $column = $this->_getPortableTableColumnDefinition($tableColumn);
743
            }
744
745
            if (! $column) {
746
                continue;
747
            }
748
749
            $name        = strtolower($column->getQuotedName($this->_platform));
750
            $list[$name] = $column;
751
        }
752
753
        return $list;
754
    }
755 296
756
    /**
757 296
     * Gets Table Column Definition.
758
     *
759 296
     * @param mixed[] $tableColumn
760 296
     */
761
    abstract protected function _getPortableTableColumnDefinition(array $tableColumn) : Column;
762
763 296
    /**
764
     * Aggregates and groups the index results according to the required data result.
765
     *
766
     * @param mixed[][] $tableIndexRows
767
     *
768
     * @return Index[]
769
     */
770
    protected function _getPortableTableIndexesList(array $tableIndexRows, string $tableName) : array
771
    {
772
        $result = [];
773
        foreach ($tableIndexRows as $tableIndex) {
774
            $indexName = $keyName = $tableIndex['key_name'];
775
            if ($tableIndex['primary']) {
776
                $keyName = 'primary';
777
            }
778
            $keyName = strtolower($keyName);
779
780
            if (! isset($result[$keyName])) {
781
                $options = [
782
                    'lengths' => [],
783
                ];
784
785
                if (isset($tableIndex['where'])) {
786
                    $options['where'] = $tableIndex['where'];
787
                }
788
789 4230
                $result[$keyName] = [
790
                    'name' => $indexName,
791 4230
                    'columns' => [],
792
                    'unique' => ! $tableIndex['non_unique'],
793 4230
                    'primary' => $tableIndex['primary'],
794 4230
                    'flags' => $tableIndex['flags'] ?? [],
795 4230
                    'options' => $options,
796 4230
                ];
797
            }
798 4230
799 3278
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
800 3278
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
801
        }
802 3278
803 3278
        $eventManager = $this->_platform->getEventManager();
804
805
        $indexes = [];
806 4230
        foreach ($result as $indexKey => $data) {
807 4230
            $index            = null;
808
            $defaultPrevented = false;
809
810 4230
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
811
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
812
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
813
814 4230
                $defaultPrevented = $eventArgs->isDefaultPrevented();
815 4230
                $index            = $eventArgs->getIndex();
816
            }
817
818 4230
            if (! $defaultPrevented) {
819
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
820
            }
821
822
            if (! $index) {
823
                continue;
824
            }
825
826
            $indexes[$indexKey] = $index;
827
        }
828
829
        return $indexes;
830
    }
831
832
    /**
833
     * @param mixed[][] $tables
834
     *
835
     * @return string[]
836
     */
837 4223
    protected function _getPortableTablesList(array $tables) : array
838
    {
839 4223
        $list = [];
840 4223
        foreach ($tables as $value) {
841 4166
            $value = $this->_getPortableTableDefinition($value);
842 4166
843 4164
            if (! $value) {
844
                continue;
845 4166
            }
846
847 4166
            $list[] = $value;
848
        }
849 4166
850
        return $list;
851
    }
852 4166
853 936
    /**
854
     * @param mixed $table
855
     */
856 4166
    protected function _getPortableTableDefinition($table) : string
857 4166
    {
858
        return $table;
859 4166
    }
860 4166
861 4166
    /**
862 4166
     * @param mixed[][] $users
863
     *
864
     * @return string[][]
865
     */
866 4166
    protected function _getPortableUsersList(array $users) : array
867 4166
    {
868
        $list = [];
869
        foreach ($users as $value) {
870 4223
            $value = $this->_getPortableUserDefinition($value);
871
872 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...
873 4223
                continue;
874 4166
            }
875 4166
876
            $list[] = $value;
877 4166
        }
878 3254
879 3254
        return $list;
880
    }
881 3254
882 3254
    /**
883
     * @param string[] $user
884
     *
885 4166
     * @return string[]
886 4166
     */
887
    protected function _getPortableUserDefinition(array $user) : array
888
    {
889 4166
        return $user;
890
    }
891
892
    /**
893 4166
     * @param mixed[][] $views
894
     *
895
     * @return View[]
896 4223
     */
897
    protected function _getPortableViewsList(array $views) : array
898
    {
899
        $list = [];
900
        foreach ($views as $value) {
901
            $view        = $this->_getPortableViewDefinition($value);
902
            $name        = strtolower($view->getQuotedName($this->_platform));
903
            $list[$name] = $view;
904 4490
        }
905
906 4490
        return $list;
907 4490
    }
908 4488
909
    /**
910 4488
     * @param mixed[] $view
911
     */
912
    protected function _getPortableViewDefinition(array $view) : View
913
    {
914 4488
        throw DBALException::notSupported('Views');
915
    }
916
917 4490
    /**
918
     * @param mixed[][] $tableForeignKeys
919
     *
920
     * @return ForeignKeyConstraint[]
921
     */
922
    protected function _getPortableTableForeignKeysList(array $tableForeignKeys) : array
923
    {
924
        $list = [];
925
926
        foreach ($tableForeignKeys as $value) {
927
            $list[] = $this->_getPortableTableForeignKeyDefinition($value);
928
        }
929
930
        return $list;
931
    }
932
933
    /**
934
     * @param mixed $tableForeignKey
935
     */
936
    protected function _getPortableTableForeignKeyDefinition($tableForeignKey) : ForeignKeyConstraint
937
    {
938
        return $tableForeignKey;
939
    }
940
941
    /**
942
     * @param string[]|string $sql
943
     */
944
    protected function _execSql($sql) : void
945
    {
946
        foreach ((array) $sql as $query) {
947
            $this->_conn->executeUpdate($query);
948
        }
949
    }
950
951
    /**
952
     * Creates a schema instance for the current database.
953
     */
954
    public function createSchema() : Schema
955
    {
956
        $namespaces = [];
957
958
        if ($this->_platform->supportsSchemas()) {
959
            $namespaces = $this->listNamespaceNames();
960
        }
961
962
        $sequences = [];
963
964
        if ($this->_platform->supportsSequences()) {
965
            $sequences = $this->listSequences();
966 3062
        }
967
968 3062
        $tables = $this->listTables();
969 3062
970 3062
        return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces);
971
    }
972 3062
973
    /**
974
     * Creates the configuration for this schema.
975
     */
976 3062
    public function createSchemaConfig() : SchemaConfig
977 3062
    {
978
        $schemaConfig = new SchemaConfig();
979
        $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
980 3062
981
        $searchPaths = $this->getSchemaSearchPaths();
982
        if (isset($searchPaths[0])) {
983
            $schemaConfig->setName($searchPaths[0]);
984
        }
985
986
        $params = $this->_conn->getParams();
987
        if (! isset($params['defaultTableOptions'])) {
988
            $params['defaultTableOptions'] = [];
989
        }
990
        if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
991
            $params['defaultTableOptions']['charset'] = $params['charset'];
992
        }
993
        $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
994
995
        return $schemaConfig;
996
    }
997
998 1482
    /**
999
     * The search path for namespaces in the currently connected database.
1000 1482
     *
1001
     * The first entry is usually the default namespace in the Schema. All
1002 1482
     * further namespaces contain tables/sequences which can also be addressed
1003 1383
     * with a short, not full-qualified name.
1004
     *
1005
     * For databases that don't support subschema/namespaces this method
1006 1482
     * returns the name of the currently connected database.
1007
     *
1008
     * @return string[]
1009
     */
1010
    public function getSchemaSearchPaths() : array
1011
    {
1012
        $database = $this->_conn->getDatabase();
1013
1014
        if ($database !== null) {
1015
            return [$database];
1016
        }
1017
1018
        return [];
1019
    }
1020
1021
    /**
1022
     * Given a table comment this method tries to extract a type hint for Doctrine Type. If the type hint is found,
1023
     * it's removed from the comment.
1024 5378
     *
1025
     * @return string|null The extracted Doctrine type or NULL of the type hint was not found.
1026 5378
     */
1027 5378
    protected function extractDoctrineTypeFromComment(?string &$comment) : ?string
1028
    {
1029 5351
        if ($comment === null || ! preg_match('/(.*)\(DC2Type:(((?!\)).)+)\)(.*)/', $comment, $match)) {
1030
            return null;
1031
        }
1032
1033
        $comment = $match[1] . $match[4];
1034
1035
        return $match[2];
1036 3923
    }
1037
}
1038