Completed
Push — master ( c7757e...39cb21 )
by Luís
16s
created

lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php (1 issue)

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\DBAL\Schema;
21
22
use Doctrine\DBAL\Events;
23
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
24
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
25
use Doctrine\DBAL\DBALException;
26
use Doctrine\DBAL\Platforms\AbstractPlatform;
27
28
/**
29
 * Base class for schema managers. Schema managers are used to inspect and/or
30
 * modify the database schema/structure.
31
 *
32
 * @author Konsta Vesterinen <[email protected]>
33
 * @author Lukas Smith <[email protected]> (PEAR MDB2 library)
34
 * @author Roman Borschel <[email protected]>
35
 * @author Jonathan H. Wage <[email protected]>
36
 * @author Benjamin Eberlei <[email protected]>
37
 * @since  2.0
38
 */
39
abstract class AbstractSchemaManager
40
{
41
    /**
42
     * Holds instance of the Doctrine connection for this schema manager.
43
     *
44
     * @var \Doctrine\DBAL\Connection
45
     */
46
    protected $_conn;
47
48
    /**
49
     * Holds instance of the database platform used for this schema manager.
50
     *
51
     * @var \Doctrine\DBAL\Platforms\AbstractPlatform
52
     */
53
    protected $_platform;
54
55
    /**
56
     * Constructor. Accepts the Connection instance to manage the schema for.
57
     *
58
     * @param \Doctrine\DBAL\Connection                      $conn
59
     * @param \Doctrine\DBAL\Platforms\AbstractPlatform|null $platform
60
     */
61 38
    public function __construct(\Doctrine\DBAL\Connection $conn, AbstractPlatform $platform = null)
62
    {
63 38
        $this->_conn     = $conn;
64 38
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
65 38
    }
66
67
    /**
68
     * Returns the associated platform.
69
     *
70
     * @return \Doctrine\DBAL\Platforms\AbstractPlatform
71
     */
72 13
    public function getDatabasePlatform()
73
    {
74 13
        return $this->_platform;
75
    }
76
77
    /**
78
     * Tries any method on the schema manager. Normally a method throws an
79
     * exception when your DBMS doesn't support it or if an error occurs.
80
     * This method allows you to try and method on your SchemaManager
81
     * instance and will return false if it does not work or is not supported.
82
     *
83
     * <code>
84
     * $result = $sm->tryMethod('dropView', 'view_name');
85
     * </code>
86
     *
87
     * @return mixed
88
     */
89 49
    public function tryMethod()
90
    {
91 49
        $args = func_get_args();
92 49
        $method = $args[0];
93 49
        unset($args[0]);
94 49
        $args = array_values($args);
95
96
        try {
97 49
            return call_user_func_array([$this, $method], $args);
98 14
        } catch (\Exception $e) {
99 14
            return false;
100
        }
101
    }
102
103
    /**
104
     * Lists the available databases for this connection.
105
     *
106
     * @return array
107
     */
108 1
    public function listDatabases()
109
    {
110 1
        $sql = $this->_platform->getListDatabasesSQL();
111
112
        $databases = $this->_conn->fetchAll($sql);
113
114
        return $this->_getPortableDatabasesList($databases);
115
    }
116
117
    /**
118
     * Returns a list of all namespaces in the current database.
119
     *
120
     * @return array
121
     */
122
    public function listNamespaceNames()
123
    {
124
        $sql = $this->_platform->getListNamespacesSQL();
125
126
        $namespaces = $this->_conn->fetchAll($sql);
127
128
        return $this->getPortableNamespacesList($namespaces);
129
    }
130
131
    /**
132
     * Lists the available sequences for this connection.
133
     *
134
     * @param string|null $database
135
     *
136
     * @return \Doctrine\DBAL\Schema\Sequence[]
137
     */
138 1
    public function listSequences($database = null)
139
    {
140 1
        if (is_null($database)) {
141
            $database = $this->_conn->getDatabase();
142
        }
143 1
        $sql = $this->_platform->getListSequencesSQL($database);
144
145 1
        $sequences = $this->_conn->fetchAll($sql);
146
147 1
        return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
148
    }
149
150
    /**
151
     * Lists the columns for a given table.
152
     *
153
     * In contrast to other libraries and to the old version of Doctrine,
154
     * this column definition does try to contain the 'primary' field for
155
     * the reason that it is not portable across different RDBMS. Use
156
     * {@see listTableIndexes($tableName)} to retrieve the primary key
157
     * of a table. We're a RDBMS specifies more details these are held
158
     * in the platformDetails array.
159
     *
160
     * @param string      $table    The name of the table.
161
     * @param string|null $database
162
     *
163
     * @return \Doctrine\DBAL\Schema\Column[]
164
     */
165 40 View Code Duplication
    public function listTableColumns($table, $database = null)
166
    {
167 40
        if ( ! $database) {
168 40
            $database = $this->_conn->getDatabase();
169
        }
170
171 40
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
172
173 40
        $tableColumns = $this->_conn->fetchAll($sql);
174
175 40
        return $this->_getPortableTableColumnList($table, $database, $tableColumns);
176
    }
177
178
    /**
179
     * Lists the indexes for a given table returning an array of Index instances.
180
     *
181
     * Keys of the portable indexes list are all lower-cased.
182
     *
183
     * @param string $table The name of the table.
184
     *
185
     * @return \Doctrine\DBAL\Schema\Index[]
186
     */
187 33
    public function listTableIndexes($table)
188
    {
189 33
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
190
191 33
        $tableIndexes = $this->_conn->fetchAll($sql);
192
193 33
        return $this->_getPortableTableIndexesList($tableIndexes, $table);
194
    }
195
196
    /**
197
     * Returns true if all the given tables exist.
198
     *
199
     * @param array $tableNames
200
     *
201
     * @return boolean
202
     */
203 55
    public function tablesExist($tableNames)
204
    {
205 55
        $tableNames = array_map('strtolower', (array) $tableNames);
206
207 55
        return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
208
    }
209
210
    /**
211
     * Returns a list of all tables in the current database.
212
     *
213
     * @return array
214
     */
215 58
    public function listTableNames()
216
    {
217 58
        $sql = $this->_platform->getListTablesSQL();
218
219 58
        $tables = $this->_conn->fetchAll($sql);
220 58
        $tableNames = $this->_getPortableTablesList($tables);
221
222 58
        return $this->filterAssetNames($tableNames);
223
    }
224
225
    /**
226
     * Filters asset names if they are configured to return only a subset of all
227
     * the found elements.
228
     *
229
     * @param array $assetNames
230
     *
231
     * @return array
232
     */
233 59
    protected function filterAssetNames($assetNames)
234
    {
235 59
        $filterExpr = $this->getFilterSchemaAssetsExpression();
236 59
        if ( ! $filterExpr) {
237 58
            return $assetNames;
238
        }
239
240 1
        return array_values(
241 1
            array_filter($assetNames, function ($assetName) use ($filterExpr) {
242 1
                $assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName;
243
244 1
                return preg_match($filterExpr, $assetName);
245 1
            })
246
        );
247
    }
248
249
    /**
250
     * @return string|null
251
     */
252 59
    protected function getFilterSchemaAssetsExpression()
253
    {
254 59
        return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();
255
    }
256
257
    /**
258
     * Lists the tables for this connection.
259
     *
260
     * @return \Doctrine\DBAL\Schema\Table[]
261
     */
262 5
    public function listTables()
263
    {
264 5
        $tableNames = $this->listTableNames();
265
266 5
        $tables = [];
267 5
        foreach ($tableNames as $tableName) {
268 4
            $tables[] = $this->listTableDetails($tableName);
269
        }
270
271 5
        return $tables;
272
    }
273
274
    /**
275
     * @param string $tableName
276
     *
277
     * @return \Doctrine\DBAL\Schema\Table
278
     */
279 29
    public function listTableDetails($tableName)
280
    {
281 29
        $columns = $this->listTableColumns($tableName);
282 29
        $foreignKeys = [];
283 29
        if ($this->_platform->supportsForeignKeyConstraints()) {
284
            $foreignKeys = $this->listTableForeignKeys($tableName);
285
        }
286 29
        $indexes = $this->listTableIndexes($tableName);
287
288 29
        return new Table($tableName, $columns, $indexes, $foreignKeys, false, []);
0 ignored issues
show
false of type false is incompatible with the type integer expected by parameter $idGeneratorType of Doctrine\DBAL\Schema\Table::__construct(). ( Ignorable by Annotation )

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

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