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

AbstractSchemaManager::removeDoctrineTypeFromComment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 1
cts 1
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 1601
     */
49
    public function __construct(Connection $conn, ?AbstractPlatform $platform = null)
50 1601
    {
51 1601
        $this->_conn     = $conn;
52 1601
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
53
    }
54
55
    /**
56
     * Returns the associated platform.
57
     */
58
    public function getDatabasePlatform() : AbstractPlatform
59 465
    {
60
        return $this->_platform;
61 465
    }
62
63
    /**
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 2290
    {
77
        $args   = func_get_args();
78 2290
        $method = $args[0];
79 2290
        unset($args[0]);
80 2290
        $args = array_values($args);
81 2290
82
        $callback = [$this, $method];
83
        assert(is_callable($callback));
84 2290
85 1691
        try {
86 1691
            return call_user_func_array($callback, $args);
87
        } catch (Throwable $e) {
88
            return false;
89
        }
90
    }
91
92
    /**
93
     * Lists the available databases for this connection.
94
     *
95 43
     * @return string[]
96
     */
97 43
    public function listDatabases() : array
98
    {
99 42
        $sql = $this->_platform->getListDatabasesSQL();
100
101 42
        $databases = $this->_conn->fetchAll($sql);
102
103
        return $this->_getPortableDatabasesList($databases);
104
    }
105
106
    /**
107
     * Returns a list of all namespaces in the current database.
108
     *
109 16
     * @return string[]
110
     */
111 16
    public function listNamespaceNames() : array
112
    {
113 16
        $sql = $this->_platform->getListNamespacesSQL();
114
115 16
        $namespaces = $this->_conn->fetchAll($sql);
116
117
        return $this->getPortableNamespacesList($namespaces);
118
    }
119
120
    /**
121
     * Lists the available sequences for this connection.
122
     *
123
     * @return Sequence[]
124
     */
125 53
    public function listSequences(?string $database = null) : array
126
    {
127 53
        if ($database === null) {
128 53
            $database = $this->_conn->getDatabase();
129
        }
130 53
        $sql = $this->_platform->getListSequencesSQL($database);
131
132 53
        $sequences = $this->_conn->fetchAll($sql);
133
134 53
        return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
135
    }
136
137
    /**
138
     * Lists the columns for a given table.
139
     *
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 1153
    {
153
        if (! $database) {
154 1153
            $database = $this->_conn->getDatabase();
155 1152
        }
156
157
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
158 1153
159
        $tableColumns = $this->_conn->fetchAll($sql);
160 1153
161
        return $this->_getPortableTableColumnList($table, $database, $tableColumns);
162 1153
    }
163
164
    /**
165
     * Lists the indexes for a given table returning an array of Index instances.
166
     *
167
     * 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 893
    {
175
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
176 893
177
        $tableIndexes = $this->_conn->fetchAll($sql);
178 893
179
        return $this->_getPortableTableIndexesList($tableIndexes, $table);
180 893
    }
181
182
    /**
183
     * Returns true if all the given tables exist.
184
     *
185
     * @param string|string[] $tableNames
186
     */
187
    public function tablesExist($tableNames) : bool
188
    {
189
        $tableNames = array_map('strtolower', (array) $tableNames);
190 1745
191
        return count($tableNames) === count(array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
192 1745
    }
193
194 1745
    /**
195
     * Returns a list of all tables in the current database.
196
     *
197
     * @return string[]
198
     */
199
    public function listTableNames() : array
200
    {
201
        $sql = $this->_platform->getListTablesSQL();
202 1761
203
        $tables     = $this->_conn->fetchAll($sql);
204 1761
        $tableNames = $this->_getPortableTablesList($tables);
205
206 1761
        return $this->filterAssetNames($tableNames);
207 1761
    }
208
209 1761
    /**
210
     * Filters asset names if they are configured to return only a subset of all
211
     * the found elements.
212
     *
213
     * @param mixed[] $assetNames
214
     *
215
     * @return mixed[]
216
     */
217
    protected function filterAssetNames(array $assetNames) : array
218
    {
219
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
220 1823
        if (! $filter) {
221
            return $assetNames;
222 1823
        }
223 1823
224 1823
        return array_values(array_filter($assetNames, $filter));
225
    }
226
227 6
    /**
228
     * @deprecated Use Configuration::getSchemaAssetsFilter() instead
229
     */
230
    protected function getFilterSchemaAssetsExpression() : ?string
231
    {
232
        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 122
        foreach ($tableNames as $tableName) {
246
            $tables[] = $this->listTableDetails($tableName);
247 122
        }
248
249 122
        return $tables;
250 122
    }
251 99
252
    public function listTableDetails(string $tableName) : Table
253
    {
254 122
        $columns     = $this->listTableColumns($tableName);
255
        $foreignKeys = [];
256
257
        if ($this->_platform->supportsForeignKeyConstraints()) {
258
            $foreignKeys = $this->listTableForeignKeys($tableName);
259
        }
260
261
        $indexes = $this->listTableIndexes($tableName);
262 824
263
        return new Table($tableName, $columns, $indexes, [], $foreignKeys, []);
264 824
    }
265 824
266
    /**
267 824
     * Lists the views this connection has.
268 750
     *
269
     * @return View[]
270
     */
271 824
    public function listViews() : array
272
    {
273 824
        $database = $this->_conn->getDatabase();
274
        $sql      = $this->_platform->getListViewsSQL($database);
275
        $views    = $this->_conn->fetchAll($sql);
276
277
        return $this->_getPortableViewsList($views);
278
    }
279
280
    /**
281 23
     * Lists the foreign keys for the given table.
282
     *
283 23
     * @param string $table The name of the table.
284 23
     *
285 23
     * @return ForeignKeyConstraint[]
286
     */
287 23
    public function listTableForeignKeys(string $table, ?string $database = null) : array
288
    {
289
        if ($database === null) {
290
            $database = $this->_conn->getDatabase();
291
        }
292
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);
293
        $tableForeignKeys = $this->_conn->fetchAll($sql);
294
295
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
296
    }
297
298 825
    /* drop*() Methods */
299
300 825
    /**
301 825
     * Drops a database.
302
     *
303 825
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
304 825
     *
305
     * @param string $database The name of the database to drop.
306 825
     */
307
    public function dropDatabase(string $database) : void
308
    {
309
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
310
    }
311
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 42
    }
321
322 42
    /**
323 31
     * Drops the index from the given table.
324
     *
325
     * @param Index|string $index The name of the index.
326
     * @param Table|string $table The name of the table.
327
     */
328
    public function dropIndex($index, $table) : void
329
    {
330
        if ($index instanceof Index) {
331
            $index = $index->getQuotedName($this->_platform);
332 2604
        }
333
334 2604
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
335 1271
    }
336
337
    /**
338
     * Drops the constraint from the given table.
339
     *
340
     * @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 23
    }
346
347 23
    /**
348
     * Drops a foreign key from a table.
349
     *
350
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
351 23
     * @param Table|string                $table      The name of the table with the foreign key.
352 23
     */
353
    public function dropForeignKey($foreignKey, $table) : void
354
    {
355
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
356
    }
357
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 18
    {
387
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
388 18
    }
389
390
    /**
391
     * Creates a new table.
392
     */
393
    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 29
399
    /**
400 29
     * Creates a new sequence.
401
     *
402
     * @throws ConnectionException If something fails at database level.
403
     */
404
    public function createSequence(Sequence $sequence) : void
405
    {
406
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
407
    }
408
409
    /**
410
     * Creates a constraint on a table.
411
     *
412 40
     * @param Table|string $table
413
     */
414 40
    public function createConstraint(Constraint $constraint, $table) : void
415 40
    {
416
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
417
    }
418
419
    /**
420
     * Creates a new index on a table.
421
     *
422 3395
     * @param Table|string $table The name of the table on which the index is to be created.
423
     */
424 3395
    public function createIndex(Index $index, $table) : void
425 3395
    {
426 2542
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
427
    }
428
429
    /**
430
     * Creates a new foreign key.
431
     *
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 44
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
438
    }
439 44
440 38
    /**
441
     * Creates a new view.
442
     */
443
    public function createView(View $view) : void
444
    {
445
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
446
    }
447
448
    /* dropAndCreate*() Methods */
449 1
450
    /**
451 1
     * Drops and creates a constraint.
452 1
     *
453
     * @see dropConstraint()
454
     * @see createConstraint()
455
     *
456
     * @param Table|string $table
457
     */
458
    public function dropAndCreateConstraint(Constraint $constraint, $table) : void
459
    {
460
        $this->tryMethod('dropConstraint', $constraint, $table);
461 23
        $this->createConstraint($constraint, $table);
462
    }
463 23
464 23
    /**
465
     * Drops and creates a new index on a table.
466
     *
467
     * @param Table|string $table The name of the table on which the index is to be created.
468
     */
469
    public function dropAndCreateIndex(Index $index, $table) : void
470
    {
471
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
472
        $this->createIndex($index, $table);
473
    }
474 44
475
    /**
476 44
     * Drops and creates a new foreign key.
477 44
     *
478
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
479
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
480
     */
481
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
482
    {
483
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
484 29
        $this->createForeignKey($foreignKey, $table);
485
    }
486 29
487 29
    /**
488
     * Drops and create a new sequence.
489
     *
490
     * @throws ConnectionException If something fails at database level.
491
     */
492
    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 23
        $this->tryMethod('dropDatabase', $database);
515
        $this->createDatabase($database);
516 23
    }
517 23
518 23
    /**
519
     * Drops and creates a new view.
520
     */
521
    public function dropAndCreateView(View $view) : void
522
    {
523
        $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 18
            $this->_execSql($ddlQuery);
542
        }
543 18
    }
544 18
545 18
    /**
546
     * Renames a given table to another name.
547
     *
548
     * @param string $name    The current name of the table.
549
     * @param string $newName The new name of the table.
550
     */
551
    public function renameTable(string $name, string $newName) : void
552 1567
    {
553
        $tableDiff          = new TableDiff($name);
554 1567
        $tableDiff->newName = $newName;
555 1567
        $this->alterTable($tableDiff);
556 1567
    }
557
558
    /**
559
     * Methods for filtering return values of list*() methods to convert
560
     * the native DBMS data definition to a portable Doctrine definition
561
     */
562
563
    /**
564
     * @param mixed[] $databases
565 43
     *
566
     * @return string[]
567 43
     */
568 43
    protected function _getPortableDatabasesList(array $databases) : array
569 43
    {
570
        $list = [];
571
        foreach ($databases as $value) {
572
            $value = $this->_getPortableDatabaseDefinition($value);
573
574
            if (! $value) {
575
                continue;
576 29
            }
577
578 29
            $list[] = $value;
579 29
        }
580 29
581
        return $list;
582
    }
583
584
    /**
585
     * 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 420
     * @return string[]
590
     */
591 420
    protected function getPortableNamespacesList(array $namespaces) : array
592
    {
593 420
        $namespacesList = [];
594 8
595
        foreach ($namespaces as $namespace) {
596
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
597 412
        }
598 412
599
        return $namespacesList;
600 412
    }
601
602
    /**
603
     * @param mixed $database
604
     *
605
     * @return mixed
606
     */
607
    protected function _getPortableDatabaseDefinition($database)
608
    {
609
        return $database;
610 1
    }
611
612 1
    /**
613 1
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
614 1
     *
615 1
     * @param mixed[] $namespace The native DBMS namespace definition.
616
     *
617
     * @return mixed
618
     */
619
    protected function getPortableNamespaceDefinition(array $namespace)
620
    {
621
        return $namespace;
622
    }
623
624
    /**
625
     * @param mixed[][] $functions
626
     *
627 42
     * @return mixed[][]
628
     */
629 42
    protected function _getPortableFunctionsList(array $functions) : array
630 42
    {
631 42
        $list = [];
632
        foreach ($functions as $value) {
633 42
            $value = $this->_getPortableFunctionDefinition($value);
634
635
            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
                continue;
637 42
            }
638
639
            $list[] = $value;
640 42
        }
641
642
        return $list;
643
    }
644
645
    /**
646
     * @param mixed[] $function
647
     *
648
     * @return mixed
649
     */
650 16
    protected function _getPortableFunctionDefinition(array $function)
651
    {
652 16
        return $function;
653
    }
654 16
655 16
    /**
656
     * @param mixed[][] $triggers
657
     *
658 16
     * @return mixed[][]
659
     */
660
    protected function _getPortableTriggersList(array $triggers) : array
661
    {
662
        $list = [];
663
        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 17
751
        return $list;
752 17
    }
753 17
754 17
    /**
755
     * Gets Table Column Definition.
756 17
     *
757
     * @param mixed[] $tableColumn
758
     */
759
    abstract protected function _getPortableTableColumnDefinition(array $tableColumn) : Column;
760 17
761
    /**
762
     * Aggregates and groups the index results according to the required data result.
763 17
     *
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 1153
                    'columns' => [],
790
                    'unique' => $tableIndex['non_unique'] ? false : true,
791 1153
                    'primary' => $tableIndex['primary'],
792
                    'flags' => $tableIndex['flags'] ?? [],
793 1153
                    'options' => $options,
794 1153
                ];
795 1153
            }
796 1153
797
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
798 1153
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
799 23
        }
800 23
801
        $eventManager = $this->_platform->getEventManager();
802 23
803 23
        $indexes = [];
804
        foreach ($result as $indexKey => $data) {
805
            $index            = null;
806 1153
            $defaultPrevented = false;
807 1153
808
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
809
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
810 1153
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
811
812
                $defaultPrevented = $eventArgs->isDefaultPrevented();
813
                $index            = $eventArgs->getIndex();
814 1153
            }
815 1153
816
            if (! $defaultPrevented) {
817
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
818 1153
            }
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
        $list = [];
838 951
        foreach ($tables as $value) {
839
            $value = $this->_getPortableTableDefinition($value);
840 951
841 951
            if (! $value) {
842 542
                continue;
843 542
            }
844 456
845
            $list[] = $value;
846 542
        }
847
848 542
        return $list;
849
    }
850 542
851
    /**
852
     * @param mixed $table
853 542
     */
854 18
    protected function _getPortableTableDefinition($table) : string
855
    {
856
        return $table;
857 542
    }
858 542
859
    /**
860 542
     * @param mixed[][] $users
861 542
     *
862 542
     * @return string[][]
863 542
     */
864
    protected function _getPortableUsersList(array $users) : array
865
    {
866
        $list = [];
867 542
        foreach ($users as $value) {
868 542
            $value = $this->_getPortableUserDefinition($value);
869
870
            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...
871 951
                continue;
872
            }
873 951
874 951
            $list[] = $value;
875 542
        }
876 542
877
        return $list;
878 542
    }
879 23
880 23
    /**
881
     * @param mixed[] $user
882 23
     *
883 23
     * @return mixed[]
884
     */
885
    protected function _getPortableUserDefinition(array $user) : array
886 542
    {
887 542
        return $user;
888
    }
889
890 542
    /**
891
     * @param mixed[][] $views
892
     *
893
     * @return View[]
894 542
     */
895
    protected function _getPortableViewsList(array $views) : array
896
    {
897 951
        $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
        return $list;
905 1761
    }
906
907 1761
    /**
908 1761
     * @param mixed[] $view
909 1738
     */
910
    protected function _getPortableViewDefinition(array $view) : View
911 1738
    {
912
        throw DBALException::notSupported('Views');
913
    }
914
915 1738
    /**
916
     * @param mixed[][] $tableForeignKeys
917
     *
918 1761
     * @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
        $tables = $this->listTables();
967 23
968
        return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces);
969 23
    }
970 23
971 23
    /**
972
     * Creates the configuration for this schema.
973 23
     */
974
    public function createSchemaConfig() : SchemaConfig
975
    {
976
        $schemaConfig = new SchemaConfig();
977 23
        $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
978 23
979
        $searchPaths = $this->getSchemaSearchPaths();
980
        if (isset($searchPaths[0])) {
981 23
            $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
     *
999 340
     * The first entry is usually the default namespace in the Schema. All
1000
     * further namespaces contain tables/sequences which can also be addressed
1001 340
     * with a short, not full-qualified name.
1002 340
     *
1003 107
     * For databases that don't support subschema/namespaces this method
1004
     * returns the name of the currently connected database.
1005 107
     *
1006
     * @return string[]
1007
     */
1008
    public function getSchemaSearchPaths() : array
1009 107
    {
1010
        $database = $this->_conn->getDatabase();
1011
1012 340
        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
    {
1025
        if ($comment === null || ! preg_match('/(.*)\(DC2Type:(((?!\)).)+)\)(.*)/', $comment, $match)) {
1026
            return null;
1027
        }
1028
1029
        $comment = $match[1] . $match[4];
1030 3729
1031
        return $match[1];
1032 3729
    }
1033
}
1034