Passed
Pull Request — 2.9 (#3692)
by
unknown
75:50 queued 13:38
created

AbstractSchemaManager::listTableNames()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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

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

329
        /** @scrutinizer ignore-call */ 
330
        $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...
330 3192
        $tableForeignKeys = $this->_conn->fetchAll($sql);
331
332 3192
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
333 1549
    }
334
335
    /* drop*() Methods */
336
337
    /**
338
     * Drops a database.
339
     *
340
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
341
     *
342
     * @param string $database The name of the database to drop.
343 27
     *
344
     * @return void
345 27
     */
346
    public function dropDatabase($database)
347
    {
348
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
349 27
    }
350 27
351
    /**
352
     * Drops the given table.
353
     *
354
     * @param string $tableName The name of the table to drop.
355
     *
356
     * @return void
357
     */
358
    public function dropTable($tableName)
359
    {
360
        $this->_execSql($this->_platform->getDropTableSQL($tableName));
361
    }
362
363
    /**
364
     * Drops the index from the given table.
365
     *
366
     * @param Index|string $index The name of the index.
367
     * @param Table|string $table The name of the table.
368
     *
369
     * @return void
370
     */
371
    public function dropIndex($index, $table)
372
    {
373
        if ($index instanceof Index) {
374
            $index = $index->getQuotedName($this->_platform);
375
        }
376
377
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
378
    }
379
380
    /**
381
     * Drops the constraint from the given table.
382
     *
383
     * @param Table|string $table The name of the table.
384 22
     *
385
     * @return void
386 22
     */
387
    public function dropConstraint(Constraint $constraint, $table)
388
    {
389
        $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
390
    }
391
392
    /**
393
     * Drops a foreign key from a table.
394
     *
395
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
396 34
     * @param Table|string                $table      The name of the table with the foreign key.
397
     *
398 34
     * @return void
399
     */
400
    public function dropForeignKey($foreignKey, $table)
401
    {
402
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
403
    }
404
405
    /**
406
     * Drops a sequence with a given name.
407
     *
408
     * @param string $name The name of the sequence to drop.
409
     *
410 46
     * @return void
411
     */
412 46
    public function dropSequence($name)
413 46
    {
414
        $this->_execSql($this->_platform->getDropSequenceSQL($name));
415
    }
416
417
    /**
418
     * Drops a view.
419
     *
420 4099
     * @param string $name The name of the view.
421
     *
422 4099
     * @return void
423 4099
     */
424 3073
    public function dropView($name)
425
    {
426
        $this->_execSql($this->_platform->getDropViewSQL($name));
427
    }
428
429
    /* create*() Methods */
430
431
    /**
432
     * Creates a new database.
433
     *
434
     * @param string $database The name of the database to create.
435 52
     *
436
     * @return void
437 52
     */
438 45
    public function createDatabase($database)
439
    {
440
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
441
    }
442
443
    /**
444
     * Creates a new table.
445
     *
446
     * @return void
447 2
     */
448
    public function createTable(Table $table)
449 2
    {
450 2
        $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
451
        $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
452
    }
453
454
    /**
455
     * Creates a new sequence.
456
     *
457
     * @param Sequence $sequence
458
     *
459 27
     * @return void
460
     *
461 27
     * @throws ConnectionException If something fails at database level.
462 27
     */
463
    public function createSequence($sequence)
464
    {
465
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
466
    }
467
468
    /**
469
     * Creates a constraint on a table.
470
     *
471
     * @param Table|string $table
472 52
     *
473
     * @return void
474 52
     */
475 52
    public function createConstraint(Constraint $constraint, $table)
476
    {
477
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
478
    }
479
480
    /**
481
     * Creates a new index on a table.
482 34
     *
483
     * @param Table|string $table The name of the table on which the index is to be created.
484 34
     *
485 34
     * @return void
486
     */
487
    public function createIndex(Index $index, $table)
488
    {
489
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
490
    }
491
492
    /**
493
     * Creates a new foreign key.
494
     *
495
     * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
496
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
497
     *
498
     * @return void
499
     */
500
    public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
501
    {
502
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
503
    }
504
505
    /**
506
     * Creates a new view.
507
     *
508
     * @return void
509
     */
510
    public function createView(View $view)
511
    {
512 27
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
513
    }
514 27
515 27
    /* dropAndCreate*() Methods */
516 27
517
    /**
518
     * Drops and creates a constraint.
519
     *
520
     * @see dropConstraint()
521
     * @see createConstraint()
522
     *
523
     * @param Table|string $table
524
     *
525
     * @return void
526
     */
527
    public function dropAndCreateConstraint(Constraint $constraint, $table)
528
    {
529
        $this->tryMethod('dropConstraint', $constraint, $table);
530
        $this->createConstraint($constraint, $table);
531
    }
532
533
    /**
534
     * Drops and creates a new index on a table.
535
     *
536
     * @param Table|string $table The name of the table on which the index is to be created.
537
     *
538
     * @return void
539 22
     */
540
    public function dropAndCreateIndex(Index $index, $table)
541 22
    {
542 22
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
543 22
        $this->createIndex($index, $table);
544
    }
545
546
    /**
547
     * Drops and creates a new foreign key.
548
     *
549
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
550 1930
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
551
     *
552 1930
     * @return void
553 1930
     */
554 1930
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
555
    {
556
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
557
        $this->createForeignKey($foreignKey, $table);
558
    }
559
560
    /**
561
     * Drops and create a new sequence.
562
     *
563 51
     * @return void
564
     *
565 51
     * @throws ConnectionException If something fails at database level.
566 51
     */
567 51
    public function dropAndCreateSequence(Sequence $sequence)
568
    {
569
        $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
570
        $this->createSequence($sequence);
571
    }
572
573
    /**
574 34
     * Drops and creates a new table.
575
     *
576 34
     * @return void
577 34
     */
578 34
    public function dropAndCreateTable(Table $table)
579
    {
580
        $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
581
        $this->createTable($table);
582
    }
583
584
    /**
585
     * Drops and creates a new database.
586
     *
587 494
     * @param string $database The name of the database to create.
588
     *
589 494
     * @return void
590 494
     */
591 10
    public function dropAndCreateDatabase($database)
592
    {
593
        $this->tryMethod('dropDatabase', $database);
594 484
        $this->createDatabase($database);
595 484
    }
596
597 484
    /**
598
     * Drops and creates a new view.
599
     *
600
     * @return void
601
     */
602
    public function dropAndCreateView(View $view)
603
    {
604
        $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
605
        $this->createView($view);
606
    }
607 2
608
    /* alterTable() Methods */
609 2
610 2
    /**
611 2
     * Alters an existing tables schema.
612 2
     *
613
     * @return void
614
     */
615
    public function alterTable(TableDiff $tableDiff)
616
    {
617
        $queries = $this->_platform->getAlterTableSQL($tableDiff);
618
        if (! is_array($queries) || ! count($queries)) {
619
            return;
620
        }
621
622
        foreach ($queries as $ddlQuery) {
623
            $this->_execSql($ddlQuery);
624 50
        }
625
    }
626 50
627 50
    /**
628 50
     * Renames a given table to another name.
629
     *
630 50
     * @param string $name    The current name of the table.
631
     * @param string $newName The new name of the table.
632
     *
633
     * @return void
634 50
     */
635
    public function renameTable($name, $newName)
636
    {
637 50
        $tableDiff          = new TableDiff($name);
638
        $tableDiff->newName = $newName;
639
        $this->alterTable($tableDiff);
640
    }
641
642
    /**
643
     * Methods for filtering return values of list*() methods to convert
644
     * the native DBMS data definition to a portable Doctrine definition
645
     */
646
647 18
    /**
648
     * @param mixed[] $databases
649 18
     *
650
     * @return string[]
651 18
     */
652 18
    protected function _getPortableDatabasesList($databases)
653
    {
654
        $list = [];
655 18
        foreach ($databases as $value) {
656
            $value = $this->_getPortableDatabaseDefinition($value);
657
658
            if (! $value) {
659
                continue;
660
            }
661
662
            $list[] = $value;
663
        }
664
665
        return $list;
666
    }
667
668
    /**
669
     * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
670
     *
671
     * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition.
672
     *
673
     * @return string[]
674
     */
675
    protected function getPortableNamespacesList(array $namespaces)
676
    {
677
        $namespacesList = [];
678
679
        foreach ($namespaces as $namespace) {
680
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
681
        }
682
683
        return $namespacesList;
684
    }
685
686
    /**
687
     * @param mixed $database
688
     *
689
     * @return mixed
690
     */
691
    protected function _getPortableDatabaseDefinition($database)
692
    {
693
        return $database;
694
    }
695
696
    /**
697
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
698
     *
699
     * @param mixed[] $namespace The native DBMS namespace definition.
700
     *
701
     * @return mixed
702
     */
703
    protected function getPortableNamespaceDefinition(array $namespace)
704
    {
705
        return $namespace;
706
    }
707
708
    /**
709
     * @param mixed[][] $functions
710
     *
711
     * @return mixed[][]
712
     */
713
    protected function _getPortableFunctionsList($functions)
714
    {
715
        $list = [];
716
        foreach ($functions as $value) {
717
            $value = $this->_getPortableFunctionDefinition($value);
718
719
            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...
720
                continue;
721
            }
722
723
            $list[] = $value;
724
        }
725
726
        return $list;
727
    }
728
729
    /**
730
     * @param mixed[] $function
731
     *
732
     * @return mixed
733
     */
734
    protected function _getPortableFunctionDefinition($function)
735
    {
736
        return $function;
737
    }
738
739
    /**
740
     * @param mixed[][] $triggers
741
     *
742
     * @return mixed[][]
743
     */
744
    protected function _getPortableTriggersList($triggers)
745
    {
746
        $list = [];
747 21
        foreach ($triggers as $value) {
748
            $value = $this->_getPortableTriggerDefinition($value);
749 21
750 21
            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...
751 21
                continue;
752
            }
753 21
754
            $list[] = $value;
755
        }
756
757 21
        return $list;
758
    }
759
760 21
    /**
761
     * @param mixed[] $trigger
762
     *
763
     * @return mixed
764
     */
765
    protected function _getPortableTriggerDefinition($trigger)
766
    {
767
        return $trigger;
768
    }
769
770
    /**
771
     * @param mixed[][] $sequences
772
     *
773
     * @return Sequence[]
774
     */
775
    protected function _getPortableSequencesList($sequences)
776
    {
777
        $list = [];
778
779
        foreach ($sequences as $value) {
780
            $list[] = $this->_getPortableSequenceDefinition($value);
781
        }
782
783
        return $list;
784
    }
785
786 1394
    /**
787
     * @param mixed[] $sequence
788 1394
     *
789
     * @return Sequence
790 1394
     *
791 1394
     * @throws DBALException
792 1380
     */
793 1380
    protected function _getPortableSequenceDefinition($sequence)
794
    {
795 1380
        throw DBALException::notSupported('Sequences');
796 27
    }
797 27
798
    /**
799 27
     * Independent of the database the keys of the column list result are lowercased.
800 27
     *
801
     * The name of the created column instance however is kept in its case.
802
     *
803 1380
     * @param string    $table        The name of the table.
804 1380
     * @param string    $database
805
     * @param mixed[][] $tableColumns
806
     *
807 1380
     * @return Column[]
808
     */
809
    protected function _getPortableTableColumnList($table, $database, $tableColumns)
810
    {
811 1380
        $eventManager = $this->_platform->getEventManager();
812 1380
813
        $list = [];
814
        foreach ($tableColumns as $tableColumn) {
815 1394
            $column           = null;
816
            $defaultPrevented = false;
817
818
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
819
                $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
820
                $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
821
822
                $defaultPrevented = $eventArgs->isDefaultPrevented();
823
                $column           = $eventArgs->getColumn();
824
            }
825
826
            if (! $defaultPrevented) {
827
                $column = $this->_getPortableTableColumnDefinition($tableColumn);
828
            }
829
830
            if (! $column) {
831
                continue;
832
            }
833
834
            $name        = strtolower($column->getQuotedName($this->_platform));
835 1173
            $list[$name] = $column;
836
        }
837 1173
838 1173
        return $list;
839 648
    }
840 648
841 533
    /**
842
     * Gets Table Column Definition.
843 648
     *
844
     * @param mixed[] $tableColumn
845 648
     *
846
     * @return Column
847 648
     */
848
    abstract protected function _getPortableTableColumnDefinition($tableColumn);
849
850 648
    /**
851 21
     * Aggregates and groups the index results according to the required data result.
852
     *
853
     * @param mixed[][]   $tableIndexRows
854 648
     * @param string|null $tableName
855 648
     *
856
     * @return Index[]
857 648
     */
858 648
    protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null)
859 648
    {
860 648
        $result = [];
861
        foreach ($tableIndexRows as $tableIndex) {
862
            $indexName = $keyName = $tableIndex['key_name'];
863
            if ($tableIndex['primary']) {
864 648
                $keyName = 'primary';
865 648
            }
866
            $keyName = strtolower($keyName);
867
868 1173
            if (! isset($result[$keyName])) {
869
                $options = [
870 1173
                    'lengths' => [],
871 1173
                ];
872 648
873 648
                if (isset($tableIndex['where'])) {
874
                    $options['where'] = $tableIndex['where'];
875 648
                }
876 27
877 27
                $result[$keyName] = [
878
                    'name' => $indexName,
879 27
                    'columns' => [],
880 27
                    'unique' => ! $tableIndex['non_unique'],
881
                    'primary' => $tableIndex['primary'],
882
                    'flags' => $tableIndex['flags'] ?? [],
883 648
                    'options' => $options,
884 648
                ];
885
            }
886
887 648
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
888
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
889
        }
890
891 648
        $eventManager = $this->_platform->getEventManager();
892
893
        $indexes = [];
894 1173
        foreach ($result as $indexKey => $data) {
895
            $index            = null;
896
            $defaultPrevented = false;
897
898
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
899
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
900
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
901
902 2106
                $defaultPrevented = $eventArgs->isDefaultPrevented();
903
                $index            = $eventArgs->getIndex();
904 2106
            }
905 2106
906 2079
            if (! $defaultPrevented) {
907
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
908 2079
            }
909
910
            if (! $index) {
911
                continue;
912 2079
            }
913
914
            $indexes[$indexKey] = $index;
915 2106
        }
916
917
        return $indexes;
918
    }
919
920
    /**
921
     * @param mixed[][] $tables
922
     *
923
     * @return string[]
924
     */
925
    protected function _getPortableTablesList($tables)
926
    {
927
        $list = [];
928
        foreach ($tables as $value) {
929
            $value = $this->_getPortableTableDefinition($value);
930
931
            if (! $value) {
932
                continue;
933
            }
934
935
            $list[] = $value;
936
        }
937
938
        return $list;
939
    }
940
941
    /**
942
     * @param mixed $table
943
     *
944
     * @return string
945
     */
946
    protected function _getPortableTableDefinition($table)
947
    {
948
        return $table;
949
    }
950
951
    /**
952
     * @param mixed[][] $users
953
     *
954
     * @return string[][]
955
     */
956
    protected function _getPortableUsersList($users)
957
    {
958
        $list = [];
959
        foreach ($users as $value) {
960
            $value = $this->_getPortableUserDefinition($value);
961
962
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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

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

Loading history...
963
                continue;
964 27
            }
965
966 27
            $list[] = $value;
967 27
        }
968 27
969
        return $list;
970 27
    }
971
972
    /**
973
     * @param string[] $user
974 27
     *
975 27
     * @return string[]
976
     */
977
    protected function _getPortableUserDefinition($user)
978 27
    {
979
        return $user;
980
    }
981
982
    /**
983
     * @param mixed[][] $views
984
     *
985
     * @return View[]
986
     */
987
    protected function _getPortableViewsList($views)
988
    {
989
        $list = [];
990
        foreach ($views as $value) {
991
            $view = $this->_getPortableViewDefinition($value);
992
993
            if (! $view) {
994
                continue;
995
            }
996 394
997
            $viewName        = strtolower($view->getQuotedName($this->_platform));
998 394
            $list[$viewName] = $view;
999 394
        }
1000 121
1001
        return $list;
1002 121
    }
1003
1004
    /**
1005
     * @param mixed[] $view
1006 121
     *
1007
     * @return View|false
1008
     */
1009 394
    protected function _getPortableViewDefinition($view)
1010
    {
1011
        return false;
1012
    }
1013
1014
    /**
1015
     * @param mixed[][] $tableForeignKeys
1016
     *
1017
     * @return ForeignKeyConstraint[]
1018
     */
1019
    protected function _getPortableTableForeignKeysList($tableForeignKeys)
1020
    {
1021
        $list = [];
1022
1023
        foreach ($tableForeignKeys as $value) {
1024
            $list[] = $this->_getPortableTableForeignKeyDefinition($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|null $comment
1125
     * @param string      $currentType
1126 1304
     *
1127
     * @return string
1128 1304
     */
1129
    public function extractDoctrineTypeFromComment($comment, $currentType)
1130
    {
1131
        if ($comment !== null && preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match)) {
1132
            return $match[1];
1133
        }
1134
1135
        return $currentType;
1136
    }
1137
1138
    /**
1139
     * @param string|null $comment
1140
     * @param string|null $type
1141
     *
1142
     * @return string|null
1143
     */
1144
    public function removeDoctrineTypeFromComment($comment, $type)
1145
    {
1146
        if ($comment === null) {
1147
            return null;
1148
        }
1149
1150
        return str_replace('(DC2Type:' . $type . ')', '', $comment);
1151
    }
1152
}
1153