Completed
Pull Request — 2.9 (#3692)
by
unknown
61:31
created

AbstractSchemaManager::listAllTableNames()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 3
c 2
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
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 call_user_func_array;
18
use function count;
19
use function func_get_args;
20
use function is_array;
21
use function preg_match;
22
use function str_replace;
23
use function strtolower;
24
25
/**
26
 * Base class for schema managers. Schema managers are used to inspect and/or
27
 * modify the database schema/structure.
28
 */
29
abstract class AbstractSchemaManager
30
{
31
    /**
32
     * Holds instance of the Doctrine connection for this schema manager.
33
     *
34
     * @var Connection
35
     */
36
    protected $_conn;
37
38
    /**
39
     * Holds instance of the database platform used for this schema manager.
40
     *
41
     * @var AbstractPlatform
42
     */
43
    protected $_platform;
44
45
    /**
46
     * Constructor. Accepts the Connection instance to manage the schema for.
47
     */
48 1934
    public function __construct(Connection $conn, ?AbstractPlatform $platform = null)
49
    {
50 1934
        $this->_conn     = $conn;
51 1934
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
52 1934
    }
53
54
    /**
55
     * Returns the associated platform.
56
     *
57
     * @return AbstractPlatform
58
     */
59 543
    public function getDatabasePlatform()
60
    {
61 543
        return $this->_platform;
62
    }
63
64
    /**
65
     * Tries any method on the schema manager. Normally a method throws an
66
     * exception when your DBMS doesn't support it or if an error occurs.
67
     * This method allows you to try and method on your SchemaManager
68
     * instance and will return false if it does not work or is not supported.
69
     *
70
     * <code>
71
     * $result = $sm->tryMethod('dropView', 'view_name');
72
     * </code>
73
     *
74
     * @return mixed
75
     */
76 2808
    public function tryMethod()
77
    {
78 2808
        $args   = func_get_args();
79 2808
        $method = $args[0];
80 2808
        unset($args[0]);
81 2808
        $args = array_values($args);
82
83
        try {
84 2808
            return call_user_func_array([$this, $method], $args);
85 2095
        } catch (Throwable $e) {
86 2095
            return false;
87
        }
88
    }
89
90
    /**
91
     * Lists the available databases for this connection.
92
     *
93
     * @return string[]
94
     */
95 51
    public function listDatabases()
96
    {
97 51
        $sql = $this->_platform->getListDatabasesSQL();
98
99 50
        $databases = $this->_conn->fetchAll($sql);
100
101 50
        return $this->_getPortableDatabasesList($databases);
102
    }
103
104
    /**
105
     * Returns a list of all namespaces in the current database.
106
     *
107
     * @return string[]
108
     */
109 18
    public function listNamespaceNames()
110
    {
111 18
        $sql = $this->_platform->getListNamespacesSQL();
112
113 18
        $namespaces = $this->_conn->fetchAll($sql);
114
115 18
        return $this->getPortableNamespacesList($namespaces);
116
    }
117
118
    /**
119
     * Lists the available sequences for this connection.
120
     *
121
     * @param string|null $database
122
     *
123
     * @return Sequence[]
124
     */
125 63
    public function listSequences($database = null)
126
    {
127 63
        if ($database === null) {
128 63
            $database = $this->_conn->getDatabase();
129
        }
130 63
        $sql = $this->_platform->getListSequencesSQL($database);
131
132 63
        $sequences = $this->_conn->fetchAll($sql);
133
134 63
        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
     * @param string|null $database
149
     *
150
     * @return Column[]
151
     */
152 1394
    public function listTableColumns($table, $database = null)
153
    {
154 1394
        if (! $database) {
155 1392
            $database = $this->_conn->getDatabase();
156
        }
157
158 1394
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
159
160 1394
        $tableColumns = $this->_conn->fetchAll($sql);
161
162 1394
        return $this->_getPortableTableColumnList($table, $database, $tableColumns);
163
    }
164
165
    /**
166
     * Lists the indexes for a given table returning an array of Index instances.
167
     *
168
     * Keys of the portable indexes list are all lower-cased.
169
     *
170
     * @param string $table The name of the table.
171
     *
172
     * @return Index[]
173
     */
174 1113
    public function listTableIndexes($table)
175
    {
176 1113
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
177
178 1113
        $tableIndexes = $this->_conn->fetchAll($sql);
179
180 1113
        return $this->_getPortableTableIndexesList($tableIndexes, $table);
181
    }
182
183
    /**
184
     * Returns true if all the given tables exist.
185
     *
186
     * @param string|string[] $tableNames
187
     * @param bool            $filtered
188
     *
189
     * @return bool
190 2078
     */
191
    public function tablesExist($tableNames, bool $filtered = true)
192 2078
    {
193
        $tableNames = array_map('strtolower', (array) $tableNames);
194 2078
195
        $tables = $filtered ? $this->listTableNames() : $this->listAllTableNames();
196
197
        return count($tableNames) === count(array_intersect($tableNames, array_map('strtolower', $tables)));
198
    }
199
200
    /**
201
     * Returns a filtered list of all tables in the current database.
202 2106
     *
203
     * @return string[]
204 2106
     */
205
    public function listTableNames()
206 2106
    {
207 2106
        $sql = $this->_platform->getListTablesSQL();
208
209 2106
        $tables     = $this->_conn->fetchAll($sql);
210
        $tableNames = $this->_getPortableTablesList($tables);
211
212
        return $this->filterAssetNames($tableNames);
213
    }
214
215
    /**
216
     * Returns a list of all tables in the current database.
217
     *
218
     * @return string[]
219
     */
220 2169
    final public function listAllTableNames(): iterable
221
    {
222 2169
        $sql = $this->_platform->getListTablesSQL();
223 2169
224 2169
        $tables = $this->_conn->fetchAll($sql);
225
226
        return $this->_getPortableTablesList($tables);
227 7
    }
228
229
    /**
230
     * Filters asset names if they are configured to return only a subset of all
231
     * the found elements.
232
     *
233
     * @param mixed[] $assetNames
234
     *
235
     * @return mixed[]
236
     */
237
    protected function filterAssetNames($assetNames)
238
    {
239
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
240
        if (! $filter) {
241
            return $assetNames;
242
        }
243
244
        return array_values(array_filter($assetNames, $filter));
245 144
    }
246
247 144
    /**
248
     * @deprecated Use Configuration::getSchemaAssetsFilter() instead
249 144
     *
250 144
     * @return string|null
251 117
     */
252
    protected function getFilterSchemaAssetsExpression()
253
    {
254 144
        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

254
        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...
255
    }
256
257
    /**
258
     * Lists the tables for this connection.
259
     *
260
     * @return Table[]
261
     */
262 1010
    public function listTables()
263
    {
264 1010
        $tableNames = $this->listTableNames();
265 1010
266 1010
        $tables = [];
267 927
        foreach ($tableNames as $tableName) {
268
            $tables[] = $this->listTableDetails($tableName);
269 1010
        }
270
271 1010
        return $tables;
272
    }
273
274
    /**
275
     * @param string $tableName
276
     *
277
     * @return Table
278
     */
279 27
    public function listTableDetails($tableName)
280
    {
281 27
        $columns     = $this->listTableColumns($tableName);
282 27
        $foreignKeys = [];
283 27
        if ($this->_platform->supportsForeignKeyConstraints()) {
284
            $foreignKeys = $this->listTableForeignKeys($tableName);
285 27
        }
286
        $indexes = $this->listTableIndexes($tableName);
287
288
        return new Table($tableName, $columns, $indexes, $foreignKeys, false, []);
289
    }
290
291
    /**
292
     * Lists the views this connection has.
293
     *
294
     * @return View[]
295
     */
296 1015
    public function listViews()
297
    {
298 1015
        $database = $this->_conn->getDatabase();
299 1015
        $sql      = $this->_platform->getListViewsSQL($database);
300
        $views    = $this->_conn->fetchAll($sql);
301 1015
302 1015
        return $this->_getPortableViewsList($views);
303
    }
304 1015
305
    /**
306
     * Lists the foreign keys for the given table.
307
     *
308
     * @param string      $table    The name of the table.
309
     * @param string|null $database
310
     *
311
     * @return ForeignKeyConstraint[]
312
     */
313
    public function listTableForeignKeys($table, $database = null)
314
    {
315
        if ($database === null) {
316
            $database = $this->_conn->getDatabase();
317
        }
318 50
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);
0 ignored issues
show
Unused Code introduced by
The call to Doctrine\DBAL\Platforms\...stTableForeignKeysSQL() has too many arguments starting with $database. ( Ignorable by Annotation )

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

318
        /** @scrutinizer ignore-call */ 
319
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
319
        $tableForeignKeys = $this->_conn->fetchAll($sql);
320 50
321 35
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
322
    }
323
324
    /* drop*() Methods */
325
326
    /**
327
     * Drops a database.
328
     *
329
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
330 3192
     *
331
     * @param string $database The name of the database to drop.
332 3192
     *
333 1549
     * @return void
334
     */
335
    public function dropDatabase($database)
336
    {
337
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
338
    }
339
340
    /**
341
     * Drops the given table.
342
     *
343 27
     * @param string $tableName The name of the table to drop.
344
     *
345 27
     * @return void
346
     */
347
    public function dropTable($tableName)
348
    {
349 27
        $this->_execSql($this->_platform->getDropTableSQL($tableName));
350 27
    }
351
352
    /**
353
     * Drops the index from the given table.
354
     *
355
     * @param Index|string $index The name of the index.
356
     * @param Table|string $table The name of the table.
357
     *
358
     * @return void
359
     */
360
    public function dropIndex($index, $table)
361
    {
362
        if ($index instanceof Index) {
363
            $index = $index->getQuotedName($this->_platform);
364
        }
365
366
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
367
    }
368
369
    /**
370
     * Drops the constraint from the given table.
371
     *
372
     * @param Table|string $table The name of the table.
373
     *
374
     * @return void
375
     */
376
    public function dropConstraint(Constraint $constraint, $table)
377
    {
378
        $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
379
    }
380
381
    /**
382
     * Drops a foreign key from a table.
383
     *
384 22
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
385
     * @param Table|string                $table      The name of the table with the foreign key.
386 22
     *
387
     * @return void
388
     */
389
    public function dropForeignKey($foreignKey, $table)
390
    {
391
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
392
    }
393
394
    /**
395
     * Drops a sequence with a given name.
396 34
     *
397
     * @param string $name The name of the sequence to drop.
398 34
     *
399
     * @return void
400
     */
401
    public function dropSequence($name)
402
    {
403
        $this->_execSql($this->_platform->getDropSequenceSQL($name));
404
    }
405
406
    /**
407
     * Drops a view.
408
     *
409
     * @param string $name The name of the view.
410 46
     *
411
     * @return void
412 46
     */
413 46
    public function dropView($name)
414
    {
415
        $this->_execSql($this->_platform->getDropViewSQL($name));
416
    }
417
418
    /* create*() Methods */
419
420 4099
    /**
421
     * Creates a new database.
422 4099
     *
423 4099
     * @param string $database The name of the database to create.
424 3073
     *
425
     * @return void
426
     */
427
    public function createDatabase($database)
428
    {
429
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
430
    }
431
432
    /**
433
     * Creates a new table.
434
     *
435 52
     * @return void
436
     */
437 52
    public function createTable(Table $table)
438 45
    {
439
        $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
440
        $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
441
    }
442
443
    /**
444
     * Creates a new sequence.
445
     *
446
     * @param Sequence $sequence
447 2
     *
448
     * @return void
449 2
     *
450 2
     * @throws ConnectionException If something fails at database level.
451
     */
452
    public function createSequence($sequence)
453
    {
454
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
455
    }
456
457
    /**
458
     * Creates a constraint on a table.
459 27
     *
460
     * @param Table|string $table
461 27
     *
462 27
     * @return void
463
     */
464
    public function createConstraint(Constraint $constraint, $table)
465
    {
466
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
467
    }
468
469
    /**
470
     * Creates a new index on a table.
471
     *
472 52
     * @param Table|string $table The name of the table on which the index is to be created.
473
     *
474 52
     * @return void
475 52
     */
476
    public function createIndex(Index $index, $table)
477
    {
478
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
479
    }
480
481
    /**
482 34
     * Creates a new foreign key.
483
     *
484 34
     * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
485 34
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
486
     *
487
     * @return void
488
     */
489
    public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
490
    {
491
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
492
    }
493
494
    /**
495
     * Creates a new view.
496
     *
497
     * @return void
498
     */
499
    public function createView(View $view)
500
    {
501
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
502
    }
503
504
    /* dropAndCreate*() Methods */
505
506
    /**
507
     * Drops and creates a constraint.
508
     *
509
     * @see dropConstraint()
510
     * @see createConstraint()
511
     *
512 27
     * @param Table|string $table
513
     *
514 27
     * @return void
515 27
     */
516 27
    public function dropAndCreateConstraint(Constraint $constraint, $table)
517
    {
518
        $this->tryMethod('dropConstraint', $constraint, $table);
519
        $this->createConstraint($constraint, $table);
520
    }
521
522
    /**
523
     * Drops and creates a new index on a table.
524
     *
525
     * @param Table|string $table The name of the table on which the index is to be created.
526
     *
527
     * @return void
528
     */
529
    public function dropAndCreateIndex(Index $index, $table)
530
    {
531
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
532
        $this->createIndex($index, $table);
533
    }
534
535
    /**
536
     * Drops and creates a new foreign key.
537
     *
538
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
539 22
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
540
     *
541 22
     * @return void
542 22
     */
543 22
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
544
    {
545
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
546
        $this->createForeignKey($foreignKey, $table);
547
    }
548
549
    /**
550 1930
     * Drops and create a new sequence.
551
     *
552 1930
     * @return void
553 1930
     *
554 1930
     * @throws ConnectionException If something fails at database level.
555
     */
556
    public function dropAndCreateSequence(Sequence $sequence)
557
    {
558
        $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
559
        $this->createSequence($sequence);
560
    }
561
562
    /**
563 51
     * Drops and creates a new table.
564
     *
565 51
     * @return void
566 51
     */
567 51
    public function dropAndCreateTable(Table $table)
568
    {
569
        $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
570
        $this->createTable($table);
571
    }
572
573
    /**
574 34
     * Drops and creates a new database.
575
     *
576 34
     * @param string $database The name of the database to create.
577 34
     *
578 34
     * @return void
579
     */
580
    public function dropAndCreateDatabase($database)
581
    {
582
        $this->tryMethod('dropDatabase', $database);
583
        $this->createDatabase($database);
584
    }
585
586
    /**
587 494
     * Drops and creates a new view.
588
     *
589 494
     * @return void
590 494
     */
591 10
    public function dropAndCreateView(View $view)
592
    {
593
        $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
594 484
        $this->createView($view);
595 484
    }
596
597 484
    /* alterTable() Methods */
598
599
    /**
600
     * Alters an existing tables schema.
601
     *
602
     * @return void
603
     */
604
    public function alterTable(TableDiff $tableDiff)
605
    {
606
        $queries = $this->_platform->getAlterTableSQL($tableDiff);
607 2
        if (! is_array($queries) || ! count($queries)) {
608
            return;
609 2
        }
610 2
611 2
        foreach ($queries as $ddlQuery) {
612 2
            $this->_execSql($ddlQuery);
613
        }
614
    }
615
616
    /**
617
     * Renames a given table to another name.
618
     *
619
     * @param string $name    The current name of the table.
620
     * @param string $newName The new name of the table.
621
     *
622
     * @return void
623
     */
624 50
    public function renameTable($name, $newName)
625
    {
626 50
        $tableDiff          = new TableDiff($name);
627 50
        $tableDiff->newName = $newName;
628 50
        $this->alterTable($tableDiff);
629
    }
630 50
631
    /**
632
     * Methods for filtering return values of list*() methods to convert
633
     * the native DBMS data definition to a portable Doctrine definition
634 50
     */
635
636
    /**
637 50
     * @param mixed[] $databases
638
     *
639
     * @return string[]
640
     */
641
    protected function _getPortableDatabasesList($databases)
642
    {
643
        $list = [];
644
        foreach ($databases as $value) {
645
            $value = $this->_getPortableDatabaseDefinition($value);
646
647 18
            if (! $value) {
648
                continue;
649 18
            }
650
651 18
            $list[] = $value;
652 18
        }
653
654
        return $list;
655 18
    }
656
657
    /**
658
     * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
659
     *
660
     * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition.
661
     *
662
     * @return string[]
663
     */
664
    protected function getPortableNamespacesList(array $namespaces)
665
    {
666
        $namespacesList = [];
667
668
        foreach ($namespaces as $namespace) {
669
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
670
        }
671
672
        return $namespacesList;
673
    }
674
675
    /**
676
     * @param mixed $database
677
     *
678
     * @return mixed
679
     */
680
    protected function _getPortableDatabaseDefinition($database)
681
    {
682
        return $database;
683
    }
684
685
    /**
686
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
687
     *
688
     * @param mixed[] $namespace The native DBMS namespace definition.
689
     *
690
     * @return mixed
691
     */
692
    protected function getPortableNamespaceDefinition(array $namespace)
693
    {
694
        return $namespace;
695
    }
696
697
    /**
698
     * @param mixed[][] $functions
699
     *
700
     * @return mixed[][]
701
     */
702
    protected function _getPortableFunctionsList($functions)
703
    {
704
        $list = [];
705
        foreach ($functions as $value) {
706
            $value = $this->_getPortableFunctionDefinition($value);
707
708
            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...
709
                continue;
710
            }
711
712
            $list[] = $value;
713
        }
714
715
        return $list;
716
    }
717
718
    /**
719
     * @param mixed[] $function
720
     *
721
     * @return mixed
722
     */
723
    protected function _getPortableFunctionDefinition($function)
724
    {
725
        return $function;
726
    }
727
728
    /**
729
     * @param mixed[][] $triggers
730
     *
731
     * @return mixed[][]
732
     */
733
    protected function _getPortableTriggersList($triggers)
734
    {
735
        $list = [];
736
        foreach ($triggers as $value) {
737
            $value = $this->_getPortableTriggerDefinition($value);
738
739
            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...
740
                continue;
741
            }
742
743
            $list[] = $value;
744
        }
745
746
        return $list;
747 21
    }
748
749 21
    /**
750 21
     * @param mixed[] $trigger
751 21
     *
752
     * @return mixed
753 21
     */
754
    protected function _getPortableTriggerDefinition($trigger)
755
    {
756
        return $trigger;
757 21
    }
758
759
    /**
760 21
     * @param mixed[][] $sequences
761
     *
762
     * @return Sequence[]
763
     */
764
    protected function _getPortableSequencesList($sequences)
765
    {
766
        $list = [];
767
        foreach ($sequences as $value) {
768
            $value = $this->_getPortableSequenceDefinition($value);
769
770
            if (! $value) {
771
                continue;
772
            }
773
774
            $list[] = $value;
775
        }
776
777
        return $list;
778
    }
779
780
    /**
781
     * @param mixed[] $sequence
782
     *
783
     * @return Sequence
784
     *
785
     * @throws DBALException
786 1394
     */
787
    protected function _getPortableSequenceDefinition($sequence)
788 1394
    {
789
        throw DBALException::notSupported('Sequences');
790 1394
    }
791 1394
792 1380
    /**
793 1380
     * Independent of the database the keys of the column list result are lowercased.
794
     *
795 1380
     * The name of the created column instance however is kept in its case.
796 27
     *
797 27
     * @param string    $table        The name of the table.
798
     * @param string    $database
799 27
     * @param mixed[][] $tableColumns
800 27
     *
801
     * @return Column[]
802
     */
803 1380
    protected function _getPortableTableColumnList($table, $database, $tableColumns)
804 1380
    {
805
        $eventManager = $this->_platform->getEventManager();
806
807 1380
        $list = [];
808
        foreach ($tableColumns as $tableColumn) {
809
            $column           = null;
810
            $defaultPrevented = false;
811 1380
812 1380
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
813
                $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
814
                $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
815 1394
816
                $defaultPrevented = $eventArgs->isDefaultPrevented();
817
                $column           = $eventArgs->getColumn();
818
            }
819
820
            if (! $defaultPrevented) {
821
                $column = $this->_getPortableTableColumnDefinition($tableColumn);
822
            }
823
824
            if (! $column) {
825
                continue;
826
            }
827
828
            $name        = strtolower($column->getQuotedName($this->_platform));
829
            $list[$name] = $column;
830
        }
831
832
        return $list;
833
    }
834
835 1173
    /**
836
     * Gets Table Column Definition.
837 1173
     *
838 1173
     * @param mixed[] $tableColumn
839 648
     *
840 648
     * @return Column
841 533
     */
842
    abstract protected function _getPortableTableColumnDefinition($tableColumn);
843 648
844
    /**
845 648
     * Aggregates and groups the index results according to the required data result.
846
     *
847 648
     * @param mixed[][]   $tableIndexRows
848
     * @param string|null $tableName
849
     *
850 648
     * @return Index[]
851 21
     */
852
    protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null)
853
    {
854 648
        $result = [];
855 648
        foreach ($tableIndexRows as $tableIndex) {
856
            $indexName = $keyName = $tableIndex['key_name'];
857 648
            if ($tableIndex['primary']) {
858 648
                $keyName = 'primary';
859 648
            }
860 648
            $keyName = strtolower($keyName);
861
862
            if (! isset($result[$keyName])) {
863
                $options = [
864 648
                    'lengths' => [],
865 648
                ];
866
867
                if (isset($tableIndex['where'])) {
868 1173
                    $options['where'] = $tableIndex['where'];
869
                }
870 1173
871 1173
                $result[$keyName] = [
872 648
                    'name' => $indexName,
873 648
                    'columns' => [],
874
                    'unique' => $tableIndex['non_unique'] ? false : true,
875 648
                    'primary' => $tableIndex['primary'],
876 27
                    'flags' => $tableIndex['flags'] ?? [],
877 27
                    'options' => $options,
878
                ];
879 27
            }
880 27
881
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
882
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
883 648
        }
884 648
885
        $eventManager = $this->_platform->getEventManager();
886
887 648
        $indexes = [];
888
        foreach ($result as $indexKey => $data) {
889
            $index            = null;
890
            $defaultPrevented = false;
891 648
892
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
893
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
894 1173
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
895
896
                $defaultPrevented = $eventArgs->isDefaultPrevented();
897
                $index            = $eventArgs->getIndex();
898
            }
899
900
            if (! $defaultPrevented) {
901
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
902 2106
            }
903
904 2106
            if (! $index) {
905 2106
                continue;
906 2079
            }
907
908 2079
            $indexes[$indexKey] = $index;
909
        }
910
911
        return $indexes;
912 2079
    }
913
914
    /**
915 2106
     * @param mixed[][] $tables
916
     *
917
     * @return string[]
918
     */
919
    protected function _getPortableTablesList($tables)
920
    {
921
        $list = [];
922
        foreach ($tables as $value) {
923
            $value = $this->_getPortableTableDefinition($value);
924
925
            if (! $value) {
926
                continue;
927
            }
928
929
            $list[] = $value;
930
        }
931
932
        return $list;
933
    }
934
935
    /**
936
     * @param mixed $table
937
     *
938
     * @return string
939
     */
940
    protected function _getPortableTableDefinition($table)
941
    {
942
        return $table;
943
    }
944
945
    /**
946
     * @param mixed[][] $users
947
     *
948
     * @return string[][]
949
     */
950
    protected function _getPortableUsersList($users)
951
    {
952
        $list = [];
953
        foreach ($users as $value) {
954
            $value = $this->_getPortableUserDefinition($value);
955
956
            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...
957
                continue;
958
            }
959
960
            $list[] = $value;
961
        }
962
963
        return $list;
964 27
    }
965
966 27
    /**
967 27
     * @param mixed[] $user
968 27
     *
969
     * @return mixed[]
970 27
     */
971
    protected function _getPortableUserDefinition($user)
972
    {
973
        return $user;
974 27
    }
975 27
976
    /**
977
     * @param mixed[][] $views
978 27
     *
979
     * @return View[]
980
     */
981
    protected function _getPortableViewsList($views)
982
    {
983
        $list = [];
984
        foreach ($views as $value) {
985
            $view = $this->_getPortableViewDefinition($value);
986
987
            if (! $view) {
988
                continue;
989
            }
990
991
            $viewName        = strtolower($view->getQuotedName($this->_platform));
992
            $list[$viewName] = $view;
993
        }
994
995
        return $list;
996 394
    }
997
998 394
    /**
999 394
     * @param mixed[] $view
1000 121
     *
1001
     * @return View|false
1002 121
     */
1003
    protected function _getPortableViewDefinition($view)
1004
    {
1005
        return false;
1006 121
    }
1007
1008
    /**
1009 394
     * @param mixed[][] $tableForeignKeys
1010
     *
1011
     * @return ForeignKeyConstraint[]
1012
     */
1013
    protected function _getPortableTableForeignKeysList($tableForeignKeys)
1014
    {
1015
        $list = [];
1016
        foreach ($tableForeignKeys as $value) {
1017
            $value = $this->_getPortableTableForeignKeyDefinition($value);
1018
1019
            if (! $value) {
1020
                continue;
1021
            }
1022
1023
            $list[] = $value;
1024
        }
1025
1026
        return $list;
1027 4511
    }
1028
1029 4511
    /**
1030 4511
     * @param mixed $tableForeignKey
1031
     *
1032 3199
     * @return ForeignKeyConstraint
1033
     */
1034
    protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
1035
    {
1036
        return $tableForeignKey;
1037
    }
1038
1039 108
    /**
1040
     * @param string[]|string $sql
1041 108
     *
1042
     * @return void
1043 108
     */
1044 9
    protected function _execSql($sql)
1045
    {
1046
        foreach ((array) $sql as $query) {
1047 108
            $this->_conn->executeUpdate($query);
1048
        }
1049 108
    }
1050 11
1051
    /**
1052
     * Creates a schema instance for the current database.
1053 108
     *
1054
     * @return Schema
1055 108
     */
1056
    public function createSchema()
1057
    {
1058
        $namespaces = [];
1059
1060
        if ($this->_platform->supportsSchemas()) {
1061
            $namespaces = $this->listNamespaceNames();
1062
        }
1063 472
1064
        $sequences = [];
1065 472
1066 472
        if ($this->_platform->supportsSequences()) {
1067
            $sequences = $this->listSequences();
1068 472
        }
1069 472
1070 354
        $tables = $this->listTables();
1071
1072
        return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces);
1073 472
    }
1074 472
1075 472
    /**
1076
     * Creates the configuration for this schema.
1077 472
     *
1078 27
     * @return SchemaConfig
1079
     */
1080 472
    public function createSchemaConfig()
1081
    {
1082 472
        $schemaConfig = new SchemaConfig();
1083
        $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
1084
1085
        $searchPaths = $this->getSchemaSearchPaths();
1086
        if (isset($searchPaths[0])) {
1087
            $schemaConfig->setName($searchPaths[0]);
1088
        }
1089
1090
        $params = $this->_conn->getParams();
1091
        if (! isset($params['defaultTableOptions'])) {
1092
            $params['defaultTableOptions'] = [];
1093
        }
1094
        if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
1095
            $params['defaultTableOptions']['charset'] = $params['charset'];
1096
        }
1097 367
        $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
1098
1099 367
        return $schemaConfig;
1100
    }
1101
1102
    /**
1103
     * The search path for namespaces in the currently connected database.
1104
     *
1105
     * The first entry is usually the default namespace in the Schema. All
1106
     * further namespaces contain tables/sequences which can also be addressed
1107
     * with a short, not full-qualified name.
1108
     *
1109
     * For databases that don't support subschema/namespaces this method
1110
     * returns the name of the currently connected database.
1111 1478
     *
1112
     * @return string[]
1113 1478
     */
1114 309
    public function getSchemaSearchPaths()
1115
    {
1116
        return [$this->_conn->getDatabase()];
1117 1478
    }
1118
1119
    /**
1120
     * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
1121
     * the type given as default.
1122
     *
1123
     * @param string $comment
1124
     * @param string $currentType
1125
     *
1126 1304
     * @return string
1127
     */
1128 1304
    public function extractDoctrineTypeFromComment($comment, $currentType)
1129
    {
1130
        if (preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match)) {
1131
            $currentType = $match[1];
1132
        }
1133
1134
        return $currentType;
1135
    }
1136
1137
    /**
1138
     * @param string $comment
1139
     * @param string $type
1140
     *
1141
     * @return string
1142
     */
1143
    public function removeDoctrineTypeFromComment($comment, $type)
1144
    {
1145
        return str_replace('(DC2Type:' . $type . ')', '', $comment);
1146
    }
1147
}
1148