Completed
Pull Request — 2.9 (#3692)
by
unknown
64:25
created

AbstractSchemaManager::listAllTableNames()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 8
ccs 5
cts 5
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, $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
    public function listAllTableNames()
221
    {
222 2169
        $sql = $this->_platform->getListTablesSQL();
223 2169
224 2169
        $tables     = $this->_conn->fetchAll($sql);
225
        $tableNames = $this->_getPortableTablesList($tables);
226
227 7
        return $tableNames;
228
    }
229
230
    /**
231
     * Filters asset names if they are configured to return only a subset of all
232
     * the found elements.
233
     *
234
     * @param mixed[] $assetNames
235
     *
236
     * @return mixed[]
237
     */
238
    protected function filterAssetNames($assetNames)
239
    {
240
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
241
        if (! $filter) {
242
            return $assetNames;
243
        }
244
245 144
        return array_values(array_filter($assetNames, $filter));
246
    }
247 144
248
    /**
249 144
     * @deprecated Use Configuration::getSchemaAssetsFilter() instead
250 144
     *
251 117
     * @return string|null
252
     */
253
    protected function getFilterSchemaAssetsExpression()
254 144
    {
255
        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

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

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