Completed
Pull Request — master (#1326)
by
unknown
02:52
created

OracleAdapter::createDatabase()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
dl 9
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 2
1
<?php
2
/**
3
 * Phinx
4
 *
5
 * (The MIT license)
6
 * Copyright (c) 2015 Rob Morgan
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated * documentation files (the "Software"), to
10
 * deal in the Software without restriction, including without limitation the
11
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12
 * sell copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
 * IN THE SOFTWARE.
25
 *
26
 * @package    Phinx
27
 * @subpackage Phinx\Db\Adapter
28
 */
29
namespace Phinx\Db\Adapter;
30
31
use Phinx\Db\Table;
32
use Phinx\Db\Table\Column;
33
use Phinx\Db\Table\ForeignKey;
34
use Phinx\Db\Table\Index;
35
use Phinx\Migration\MigrationInterface;
36
37
/**
38
 * Phinx Oracle Adapter.
39
 *
40
 * @author Felipe Maia <[email protected]>
41
 */
42
class OracleAdapter extends PdoAdapter implements AdapterInterface
0 ignored issues
show
Bug introduced by
There is at least one abstract method in this class. Maybe declare it as abstract, or implement the remaining methods: getAddColumnInstructions, getAddForeignKeyInstructions, getAddIndexInstructions, getChangeColumnInstructions, getDropColumnInstructions, getDropForeignKeyByColumnsInstructions, getDropForeignKeyInstructions, getDropIndexByColumnsInstructions, getDropIndexByNameInstructions, getDropTableInstructions, getRenameColumnInstructions, getRenameTableInstructions
Loading history...
43
{
44
    protected $schema = 'dbo';
45
46
    protected $signedColumnTypes = ['integer' => true, 'biginteger' => true, 'float' => true, 'decimal' => true];
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function connect()
52
    {
53
        if ($this->connection === null) {
54
            if (!extension_loaded('pdo_oci')) {
55
                // @codeCoverageIgnoreStart
56
                throw new \RuntimeException('You need to enable the PDO_OCI extension for Phinx to run properly.');
57
                // @codeCoverageIgnoreEnd
58
            }
59
60
            $options = $this->getOptions();
61
62
            // if port is specified use it, otherwise use the Oracle default
63 View Code Duplication
            if (empty($options['port'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
64
                $dsn = "oci:dbname=//" . $options['host'] . "/" . $options['sid'] . "";
65
            } else {
66
                $dsn = "oci:dbname=//" . $options['host'] . ":" . $options['port'] . "/" . $options['sid'] . "";
67
            }
68
69
            $driverOptions = [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION];
70
71
            try {
72
                $db = new \PDO($dsn, $options['user'], $options['pass'], $driverOptions);
73
            } catch (\PDOException $exception) {
74
                throw new \InvalidArgumentException(sprintf(
75
                    'There was a problem connecting to the database: %s',
76
                    $exception->getMessage()
77
                ));
78
            }
79
            $this->setConnection($db);
80
        }
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function disconnect()
87
    {
88
        $this->connection = null;
89
    }
90
91
    /**
92
     * @codeCoverageIgnore
93
     * {@inheritdoc}
94
     */
95
    public function hasTransactions()
96
    {
97
        return true;
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     * @codeCoverageIgnore
103
     */
104
    public function beginTransaction()
105
    {
106
//        $this->execute('BEGIN TRANSACTION');
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     * @codeCoverageIgnore
112
     */
113
    public function commitTransaction()
114
    {
115
//        $this->execute('COMMIT TRANSACTION');
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     * @codeCoverageIgnore
121
     */
122
    public function rollbackTransaction()
123
    {
124
//        $this->execute('ROLLBACK TRANSACTION');
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130
    public function quoteTableName($tableName)
131
    {
132
        return str_replace('.', '].[', $this->quoteColumnName($tableName));
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138
    public function quoteColumnName($columnName)
139
    {
140
        return '"' . str_replace(']', '"', $columnName) . '"';
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public function hasTable($tableName)
147
    {
148
        $result = $this->fetchRow(
149
            sprintf(
150
                'SELECT count(*) as count FROM ALL_TABLES WHERE table_name = \'%s\'',
151
                $tableName
152
            )
153
        );
154
155
        return $result['COUNT'] > 0;
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    public function createTable(Table $table)
162
    {
163
        $options = $table->getOptions();
164
165
        // Add the default primary key
166
        $columns = $table->getPendingColumns();
0 ignored issues
show
Bug introduced by
The method getPendingColumns() does not seem to exist on object<Phinx\Db\Table>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
167
168
        if (!isset($options['id']) || (isset($options['id']) && $options['id'] === true)) {
169
            $column = new Column();
170
            $column->setName('id')
171
                ->setType('integer')
172
                ->setIdentity(true);
173
174
            array_unshift($columns, $column);
175
            $options['primary_key'] = 'id';
176
        } elseif (isset($options['id']) && is_string($options['id'])) {
177
            // Handle id => "field_name" to support AUTO_INCREMENT
178
            $column = new Column();
179
            $column->setName($options['id'])
180
                ->setType('integer')
181
                ->setIdentity(true);
182
183
            array_unshift($columns, $column);
184
            $options['primary_key'] = $options['id'];
185
        }
186
187
        $sql = 'CREATE TABLE ';
188
        $sql .= $this->quoteTableName($table->getName()) . ' (';
189
        $sqlBuffer = [];
190
        $columnsWithComments = [];
191
192 View Code Duplication
        foreach ($columns as $column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
            $sqlBuffer[] = $this->quoteColumnName($column->getName()) . ' ' . $this->getColumnSqlDefinition($column);
194
195
            // set column comments, if needed
196
            if ($column->getComment()) {
197
                $columnsWithComments[] = $column;
198
            }
199
        }
200
201
        // set the primary key(s)
202 View Code Duplication
        if (isset($options['primary_key'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
203
            $pkSql = sprintf('CONSTRAINT PK_%s PRIMARY KEY (', substr($table->getName(), 0, 28));
204
            if (is_string($options['primary_key'])) { // handle primary_key => 'id'
205
                $pkSql .= $this->quoteColumnName($options['primary_key']);
206
            } elseif (is_array($options['primary_key'])) { // handle primary_key => array('tag_id', 'resource_id')
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
207
                $pkSql .= implode(',', array_map([$this, 'quoteColumnName'], $options['primary_key']));
208
            }
209
            $pkSql .= ')';
210
            $sqlBuffer[] = $pkSql;
211
        }
212
213
        // set the foreign keys
214
        $foreignKeys = $table->getForeignKeys();
0 ignored issues
show
Bug introduced by
The method getForeignKeys() does not seem to exist on object<Phinx\Db\Table>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
215
        foreach ($foreignKeys as $key => $foreignKey) {
216
            $sqlBuffer[] = $this->getForeignKeySqlDefinition($foreignKey, $table->getName());
217
        }
218
219
        $sql .= implode(', ', $sqlBuffer);
220
        $sql .= ')';
221
222
        $this->execute($sql);
223
        // process column comments
224
        foreach ($columnsWithComments as $key => $column) {
225
            $sql = $this->getColumnCommentSqlDefinition($column, $table->getName());
226
            $this->execute($sql);
227
        }
228
        // set the indexes
229
        $indexes = $table->getIndexes();
0 ignored issues
show
Bug introduced by
The method getIndexes() does not seem to exist on object<Phinx\Db\Table>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
230
231
        if (!empty($indexes)) {
232
            foreach ($indexes as $index) {
233
                $sql = $this->getIndexSqlDefinition($index, $table->getName());
234
                $this->execute($sql);
235
            }
236
        }
237
238
        if (!$this->hasSequence($table->getName())) {
239
            $sql = "CREATE SEQUENCE SQ_" . $table->getName() . " MINVALUE 1 MAXVALUE 99999999999999999 INCREMENT BY 1";
240
            $this->execute($sql);
241
        }
242
    }
243
244
    /**
245
     * Verify if the table has a Sequence for primary Key
246
     *
247
     * @param string $tableName Table name
248
     *
249
     * @return bool
250
     */
251
    public function hasSequence($tableName)
252
    {
253
        $sql = sprintf(
254
            "SELECT COUNT(*) as COUNT FROM user_sequences WHERE sequence_name = '%s'",
255
            strtoupper("SQ_" . $tableName)
256
        );
257
        $result = $this->fetchRow($sql);
258
259
        return $result['COUNT'] > 0;
260
    }
261
262
    /**
263
     * Gets the Oracle Column Comment Defininition for a column object.
264
     *
265
     * @param \Phinx\Db\Table\Column $column    Column
266
     * @param string $tableName Table name
267
     *
268
     * @return string
269
     */
270
    protected function getColumnCommentSqlDefinition(Column $column, $tableName)
271
    {
272
        $comment = (strcasecmp($column->getComment(), 'NULL') !== 0) ? $column->getComment() : '';
273
274
        return sprintf(
275
            "COMMENT ON COLUMN \"%s\".\"%s\" IS '%s'",
276
            $tableName,
277
            $column->getName(),
278
            str_replace("'", "", $comment)
279
        );
280
    }
281
282
    /**
283
     * {@inheritdoc}
284
     */
285
    public function renameTable($tableName, $newTableName)
286
    {
287
        $this->execute(sprintf('alter table "%s" rename to "%s"', $tableName, $newTableName));
288
289
        if (!$this->hasSequence("SQ_" . strtoupper($newTableName))) {
290
            $this->renameSequence("SQ_" . strtoupper($tableName), "SQ_" . strtoupper($newTableName));
291
        }
292
    }
293
294
    /**
295
     * Rename an Oracle Sequence Object.
296
     *
297
     * @param string $sequenceName Old Sequence Name
298
     * @param string $newSequenceName New Sequence Name
299
     *
300
     * @return void
301
     */
302
    public function renameSequence($sequenceName, $newSequenceName)
303
    {
304
        $this->execute(sprintf('rename "%s" to "%s"', $sequenceName, $newSequenceName));
305
    }
306
307
    /**
308
     * {@inheritdoc}
309
     */
310
    public function dropTable($tableName)
311
    {
312
        $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tableName)));
313
        $this->execute(sprintf('DROP SEQUENCE %s', $this->quoteTableName(strtoupper("SQ_" . $tableName))));
314
    }
315
316
    /**
317
     * {@inheritdoc}
318
     */
319
    public function truncateTable($tableName)
320
    {
321
        $sql = sprintf(
322
            'TRUNCATE TABLE %s',
323
            $this->quoteTableName($tableName)
324
        );
325
326
        $this->execute($sql);
327
    }
328
329
    /**
330
     * Get the comment for a column
331
     *
332
     * @param string $tableName Table Name
333
     * @param string $columnName Column Name
334
     *
335
     * @return string
336
     */
337
    public function getColumnComment($tableName, $columnName)
338
    {
339
        $sql = sprintf(
340
            "select COMMENTS from ALL_COL_COMMENTS WHERE COLUMN_NAME = '%s' and TABLE_NAME = '%s'",
341
            $columnName,
342
            $tableName
343
        );
344
        $row = $this->fetchRow($sql);
345
346
        return $row['COMMENTS'];
347
    }
348
349
    /**
350
     * {@inheritdoc}
351
     */
352
    public function getColumns($tableName)
353
    {
354
        $columns = [];
355
356
        $sql = sprintf(
357
            "select TABLE_NAME \"TABLE_NAME\", COLUMN_NAME \"NAME\", DATA_TYPE \"TYPE\", NULLABLE \"NULL\", 
358
            DATA_DEFAULT \"DEFAULT\", DATA_LENGTH \"CHAR_LENGTH\", DATA_PRECISION \"PRECISION\", DATA_SCALE \"SCALE\", 
359
            COLUMN_ID \"ORDINAL_POSITION\" FROM ALL_TAB_COLUMNS WHERE table_name = '%s'",
360
            $tableName
361
        );
362
363
        $rows = $this->fetchAll($sql);
364
365
        foreach ($rows as $columnInfo) {
366
            $default = null;
367
            if (trim($columnInfo['DEFAULT']) != 'NULL') {
368
                $default = trim($columnInfo['DEFAULT']);
369
            }
370
371
            $column = new Column();
372
            $column->setName($columnInfo['NAME'])
373
                ->setType($this->getPhinxType($columnInfo['TYPE'], $columnInfo['PRECISION']))
374
                ->setNull($columnInfo['NULL'] !== 'N')
375
                ->setDefault($default)
376
                ->setComment($this->getColumnComment($columnInfo['TABLE_NAME'], $columnInfo['NAME']));
377
378
            if (!empty($columnInfo['CHAR_LENGTH'])) {
379
                $column->setLimit($columnInfo['CHAR_LENGTH']);
380
            }
381
382
            $columns[$columnInfo['NAME']] = $column;
383
        }
384
385
        return $columns;
386
    }
387
388
    /**
389
     * {@inheritdoc}
390
     */
391 View Code Duplication
    public function hasColumn($tableName, $columnName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
392
    {
393
        $sql = sprintf(
394
            "select count(*) as count from ALL_TAB_COLUMNS 
395
            where table_name = '%s' and column_name = '%s'",
396
            $tableName,
397
            $columnName
398
        );
399
400
        $result = $this->fetchRow($sql);
401
402
        return $result['COUNT'] > 0;
403
    }
404
405
    /**
406
     * {@inheritdoc}
407
     */
408
    public function addColumn(Table $table, Column $column)
409
    {
410
        $sql = sprintf(
411
            'ALTER TABLE %s ADD %s %s',
412
            $this->quoteTableName($table->getName()),
413
            $this->quoteColumnName($column->getName()),
414
            $this->getColumnSqlDefinition($column)
415
        );
416
417
        $this->execute($sql);
418
    }
419
420
    /**
421
     * {@inheritdoc}
422
     */
423
    public function renameColumn($tableName, $columnName, $newColumnName)
424
    {
425
        if (!$this->hasColumn($tableName, $columnName)) {
426
            throw new \InvalidArgumentException("The specified column does not exist: $columnName");
427
        }
428
429
        $this->execute(
430
            sprintf(
431
                "alter table \"%s\" rename column \"%s\" TO \"%s\"",
432
                $tableName,
433
                $columnName,
434
                $newColumnName
435
            )
436
        );
437
    }
438
439
    /**
440
     * {@inheritdoc}
441
     */
442
    public function changeColumn($tableName, $columnName, Column $newColumn)
443
    {
444
        $columns = $this->getColumns($tableName);
445
446
        if ($columnName !== $newColumn->getName()) {
447
            $this->renameColumn($tableName, $columnName, $newColumn->getName());
448
        }
449
450
        $setNullSql = ($newColumn->isNull() == $columns[$columnName]->isNull() ? false : true);
451
452
        $this->execute(
453
            sprintf(
454
                'ALTER TABLE %s MODIFY(%s %s)',
455
                $this->quoteTableName($tableName),
456
                $this->quoteColumnName($newColumn->getName()),
457
                $this->getColumnSqlDefinition($newColumn, $setNullSql)
458
            )
459
        );
460
        // change column comment if needed
461
        if ($newColumn->getComment()) {
462
            $sql = $this->getColumnCommentSqlDefinition($newColumn, $tableName);
463
            $this->execute($sql);
464
        }
465
    }
466
467
    /**
468
     * {@inheritdoc}
469
     */
470
    public function dropColumn($tableName, $columnName)
471
    {
472
        $this->execute(
473
            sprintf(
474
                'ALTER TABLE %s DROP COLUMN %s',
475
                $this->quoteTableName($tableName),
476
                $this->quoteColumnName($columnName)
477
            )
478
        );
479
    }
480
481
    /**
482
     * Get an array of indexes from a particular table.
483
     *
484
     * @param string $tableName Table Name
485
     * @return array
486
     */
487 View Code Duplication
    public function getIndexes($tableName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
488
    {
489
        $indexes = [];
490
        $sql = "SELECT index_owner as owner,index_name,column_name FROM ALL_IND_COLUMNS 
491
                WHERE TABLE_NAME = '$tableName'";
492
493
        $rows = $this->fetchAll($sql);
494
        foreach ($rows as $row) {
495
            if (!isset($indexes[$row['INDEX_NAME']])) {
496
                $indexes[$row['INDEX_NAME']] = ['columns' => []];
497
            }
498
            $indexes[$row['INDEX_NAME']]['columns'][] = strtoupper($row['COLUMN_NAME']);
499
        }
500
501
        return $indexes;
502
    }
503
504
    /**
505
     * {@inheritdoc}
506
     */
507
    public function hasIndex($tableName, $columns)
508
    {
509
        if (is_string($columns)) {
510
            $columns = [$columns]; // str to array
511
        }
512
513
        $indexes = $this->getIndexes($tableName);
514
        foreach ($indexes as $index) {
515
            $a = array_diff($columns, $index['columns']);
516
517
            if (empty($a)) {
518
                return true;
519
            }
520
        }
521
522
        return false;
523
    }
524
525
    /**
526
     * {@inheritdoc}
527
     */
528 View Code Duplication
    public function hasIndexByName($tableName, $indexName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
529
    {
530
        $indexes = $this->getIndexes($tableName);
531
532
        foreach ($indexes as $name => $index) {
533
            if ($name === $indexName) {
534
                return true;
535
            }
536
        }
537
538
        return false;
539
    }
540
541
    /**
542
     * {@inheritdoc}
543
     */
544
    public function addIndex(Table $table, Index $index)
545
    {
546
        $sql = $this->getIndexSqlDefinition($index, $table->getName());
547
        $this->execute($sql);
548
    }
549
550
    /**
551
     * {@inheritdoc}
552
     */
553
    public function dropIndex($tableName, $columns)
554
    {
555
        if (is_string($columns)) {
556
            $columns = [$columns]; // str to array
557
        }
558
559
        $indexes = $this->getIndexes($tableName);
560
        $columns = array_map('strtoupper', $columns);
561
562 View Code Duplication
        foreach ($indexes as $indexName => $index) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
563
            $a = array_diff($columns, $index['columns']);
564
            if (empty($a)) {
565
                $this->execute(
566
                    sprintf(
567
                        'DROP INDEX %s',
568
                        $this->quoteColumnName($indexName)
569
                    )
570
                );
571
572
                break;
573
            }
574
        }
575
    }
576
577
    /**
578
     * {@inheritdoc}
579
     */
580
    public function dropIndexByName($tableName, $indexName)
581
    {
582
        $indexes = $this->getIndexes($tableName);
583
584 View Code Duplication
        foreach ($indexes as $name => $index) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
585
            if ($name === $indexName) {
586
                $this->execute(
587
                    sprintf(
588
                        'DROP INDEX %s',
589
                        $this->quoteColumnName($indexName)
590
                    )
591
                );
592
593
                break;
594
            }
595
        }
596
    }
597
598
    /**
599
     * {@inheritdoc}
600
     */
601 View Code Duplication
    public function hasForeignKey($tableName, $columns, $constraint = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
602
    {
603
        if (is_string($columns)) {
604
            $columns = [$columns]; // str to array
605
        }
606
        $foreignKeys = $this->getForeignKeys($tableName);
607
608
        if ($constraint) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $constraint of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
609
            if (isset($foreignKeys[$constraint])) {
610
                return !empty($foreignKeys[$constraint]);
611
            }
612
613
            return false;
614
        } else {
615
            foreach ($foreignKeys as $key) {
616
                $a = array_diff($columns, $key['COLUMNS']);
617
                if (empty($a)) {
618
                    return true;
619
                }
620
            }
621
622
            return false;
623
        }
624
    }
625
626
    /**
627
     * Get an array of foreign keys from a particular table.
628
     *
629
     * @param string $tableName Table Name
630
     * @param string $type Type of Constraint Type (R, P)
631
     * @return array
632
     */
633 View Code Duplication
    protected function getForeignKeys($tableName, $type = 'R')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
634
    {
635
        $foreignKeys = [];
636
        $rows = $this->fetchAll(sprintf(
637
            "SELECT a.CONSTRAINT_NAME, a.TABLE_NAME, b.COLUMN_NAME, 
638
                    (SELECT c.TABLE_NAME from ALL_CONS_COLUMNS c 
639
                    WHERE c.CONSTRAINT_NAME = a.R_CONSTRAINT_NAME) referenced_table_name,
640
                    (SELECT c.COLUMN_NAME from ALL_CONS_COLUMNS c 
641
                    WHERE c.CONSTRAINT_NAME = a.R_CONSTRAINT_NAME) referenced_column_name
642
                    FROM all_constraints a JOIN ALL_CONS_COLUMNS b ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
643
                    WHERE a.table_name = '%s'
644
                    AND CONSTRAINT_TYPE = '%s'",
645
            $tableName,
646
            $type
647
        ));
648
649
        foreach ($rows as $row) {
650
            $foreignKeys[$row['CONSTRAINT_NAME']]['TABLE'] = $row['TABLE_NAME'];
651
            $foreignKeys[$row['CONSTRAINT_NAME']]['COLUMNS'][] = $row['COLUMN_NAME'];
652
            $foreignKeys[$row['CONSTRAINT_NAME']]['REFERENCED_TABLE'] = $row['REFERENCED_TABLE_NAME'];
653
            $foreignKeys[$row['CONSTRAINT_NAME']]['REFERENCED_COLUMNS'][] = $row['REFERENCED_COLUMN_NAME'];
654
        }
655
656
        return $foreignKeys;
657
    }
658
659
    /**
660
     * {@inheritdoc}
661
     */
662
    public function addForeignKey(Table $table, ForeignKey $foreignKey)
663
    {
664
        $this->execute(
665
            sprintf(
666
                'ALTER TABLE %s ADD %s',
667
                $this->quoteTableName($table->getName()),
668
                $this->getForeignKeySqlDefinition($foreignKey, $table->getName())
669
            )
670
        );
671
    }
672
673
    /**
674
     * {@inheritdoc}
675
     */
676
    public function dropForeignKey($tableName, $columns, $constraint = null)
677
    {
678
        if (is_string($columns)) {
679
            $columns = [$columns]; // str to array
680
        }
681
682
        if ($constraint) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $constraint of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
683
            $this->execute(
684
                sprintf(
685
                    'ALTER TABLE %s DROP CONSTRAINT %s',
686
                    $this->quoteTableName($tableName),
687
                    $constraint
688
                )
689
            );
690
691
            return;
692
        } else {
693 View Code Duplication
            foreach ($columns as $column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
694
                $rows = $this->fetchAll(sprintf(
695
                    "SELECT a.CONSTRAINT_NAME, a.TABLE_NAME, b.COLUMN_NAME, 
696
                    (SELECT c.TABLE_NAME from ALL_CONS_COLUMNS c 
697
                    WHERE c.CONSTRAINT_NAME = a.R_CONSTRAINT_NAME) referenced_table_name,
698
                    (SELECT c.COLUMN_NAME from ALL_CONS_COLUMNS c 
699
                    WHERE c.CONSTRAINT_NAME = a.R_CONSTRAINT_NAME) referenced_column_name
700
                    FROM all_constraints a JOIN ALL_CONS_COLUMNS b ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
701
                    WHERE a.table_name = '%s'
702
                    AND CONSTRAINT_TYPE = 'R'
703
                    AND COLUMN_NAME = '%s'",
704
                    $tableName,
705
                    $column
706
                ));
707
                foreach ($rows as $row) {
708
                    $this->dropForeignKey($tableName, $columns, $row['CONSTRAINT_NAME']);
709
                }
710
            }
711
        }
712
    }
713
714
    /**
715
     * {@inheritdoc}
716
     */
717
    public function getSqlType($type, $limit = null)
718
    {
719
//      reference: https://docs.oracle.com/cd/B19306_01/gateways.102/b14270/apa.htm
720
        switch ($type) {
721
            case static::PHINX_TYPE_STRING:
722
                return ['name' => 'VARCHAR2', 'limit' => 255];
723
            case static::PHINX_TYPE_CHAR:
724
                return ['name' => 'CHAR', 'limit' => 255];
725
            case static::PHINX_TYPE_TEXT:
726
                return ['name' => 'LONG'];
727
            case static::PHINX_TYPE_INTEGER:
728
                return ['name' => 'NUMBER', 'precision' => 10];
729
            case static::PHINX_TYPE_BIG_INTEGER:
730
                return ['name' => 'NUMBER', 'precision' => 19];
731
            case static::PHINX_TYPE_FLOAT:
732
                return ['name' => 'FLOAT', 'precision' => 49];
733
            case static::PHINX_TYPE_DECIMAL:
734
                return ['name' => 'NUMBER'];
735
            case static::PHINX_TYPE_DATETIME:
736
                return ['name' => 'DATE'];
737
            case static::PHINX_TYPE_TIMESTAMP:
738
                return ['name' => 'TIMESTAMP'];
739
            case static::PHINX_TYPE_TIME:
740
                return ['name' => 'time'];
741
            case static::PHINX_TYPE_DATE:
742
                return ['name' => 'DATE'];
743
            case static::PHINX_TYPE_BLOB:
744
                return ['name' => 'BLOB'];
745
            case 'CLOB':
746
                return ['name' => 'CLOB'];
747
            case static::PHINX_TYPE_BINARY:
748
                return ['name' => 'RAW', 'limit' => 2000];
749
            case static::PHINX_TYPE_BOOLEAN:
750
                return ['name' => 'NUMBER', 'precision' => 1];
751
            case static::PHINX_TYPE_UUID:
752
                return ['name' => 'RAW', 'precision' => 16, 'default' => 'SYS_GUID()', 'limit' => 2000];
753
            case static::PHINX_TYPE_FILESTREAM:
754
                return ['name' => 'varbinary', 'limit' => 'max'];
755
            // Geospatial database types
756
            case static::PHINX_TYPE_GEOMETRY:
757
            case static::PHINX_TYPE_POINT:
758
            case static::PHINX_TYPE_LINESTRING:
759
            case static::PHINX_TYPE_POLYGON:
760
                // SQL Server stores all spatial data using a single data type.
761
                // Specific types (point, polygon, etc) are set at insert time.
762
                return ['name' => 'geography'];
763
            default:
764
                throw new \RuntimeException('The type: "' . $type . '" is not supported.');
765
        }
766
    }
767
768
    /**
769
     * Returns Phinx type by SQL type
770
     *
771
     * @param string $sqlType SQL Type definition
772
     * @param int $precision Precision of NUMBER type to define Phinx Type.
773
     * @throws \RuntimeException
774
     * @internal param string $sqlType SQL type
775
     * @return string Phinx type
776
     */
777
    public function getPhinxType($sqlType, $precision = null)
778
    {
779
        if ($sqlType === 'VARCHAR2') {
780
            return static::PHINX_TYPE_STRING;
781
        } elseif ($sqlType === 'CHAR') {
782
            return static::PHINX_TYPE_CHAR;
783
        } elseif ($sqlType == 'LONG') {
784
            return static::PHINX_TYPE_TEXT;
785
        } elseif ($sqlType === 'NUMBER' && $precision === 10) {
786
            return static::PHINX_TYPE_INTEGER;
787
        } elseif ($sqlType === 'NUMBER' && $precision === 19) {
788
            return static::PHINX_TYPE_BIG_INTEGER;
789
        } elseif ($sqlType === 'FLOAT') {
790
            return static::PHINX_TYPE_FLOAT;
791
        } elseif ($sqlType === 'TIMESTAMP(6)') {
792
            return static::PHINX_TYPE_TIMESTAMP;
793
        } elseif ($sqlType === 'TIME') {
794
            return static::PHINX_TYPE_TIME;
795
        } elseif ($sqlType === 'DATE') {
796
            return static::PHINX_TYPE_DATE;
797
        } elseif ($sqlType === 'BLOB') {
798
            return static::PHINX_TYPE_BLOB;
799
        } elseif ($sqlType === 'CLOB') {
800
            return 'CLOB';
801
        } elseif ($sqlType === 'RAW' && $precision === 16) {
802
            return static::PHINX_TYPE_UUID;
803
        } elseif ($sqlType === 'RAW') {
804
            return static::PHINX_TYPE_BLOB;
805
        } elseif ($sqlType === 'NUMBER' && $precision === 1) {
806
            return static::PHINX_TYPE_BOOLEAN;
807
        } elseif ($sqlType === 'NUMBER') {
808
            return static::PHINX_TYPE_DECIMAL;
809
        } else {
810
            throw new \RuntimeException('The Oracle type: "' . $sqlType . '" is not supported');
811
        }
812
    }
813
814
    /**
815
     * {@inheritdoc}
816
     */
817 View Code Duplication
    public function createDatabase($name, $options = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
818
    {
819
        if (isset($options['collation'])) {
820
            $this->execute(sprintf('CREATE DATABASE [%s] COLLATE [%s]', $name, $options['collation']));
821
        } else {
822
            $this->execute(sprintf('CREATE DATABASE [%s]', $name));
823
        }
824
        $this->execute(sprintf('USE [%s]', $name));
825
    }
826
827
    /**
828
     * {@inheritdoc}
829
     */
830
    public function hasDatabase($name)
831
    {
832
        $result = $this->fetchRow(
833
            sprintf(
834
                'SELECT count(*) as [count] FROM master.dbo.sysdatabases WHERE [name] = \'%s\'',
835
                $name
836
            )
837
        );
838
839
        return $result['count'] > 0;
840
    }
841
842
    /**
843
     * {@inheritdoc}
844
     */
845
    public function dropDatabase($name)
846
    {
847
        $sql = <<<SQL
848
USE master;
849
IF EXISTS(select * from sys.databases where name=N'$name')
850
ALTER DATABASE [$name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
851
DROP DATABASE [$name];
852
SQL;
853
        $this->execute($sql);
854
    }
855
856
    /**
857
     * Get the defintion for a `DEFAULT` statement.
858
     *
859
     * @param  mixed $default Default value for column
860
     * @return string
861
     */
862
    protected function getDefaultValueDefinition($default)
863
    {
864
        if (is_string($default) && 'CURRENT_TIMESTAMP' !== $default && 'SYSDATE' !== $default) {
865
            $default = $this->getConnection()->quote($default);
866
        } elseif (is_bool($default)) {
867
            $default = $this->castToBool($default);
868
        }
869
870
        return isset($default) ? ' DEFAULT ' . $default : 'DEFAULT NULL';
871
    }
872
873
    /**
874
     * Gets the Oracle Column Definition for a Column object.
875
     *
876
     * @param \Phinx\Db\Table\Column $column Column
877
     * @param bool $setNullSql Set column nullable
878
     * @return string
879
     */
880
    protected function getColumnSqlDefinition(Column $column, $setNullSql = true)
881
    {
882
        $buffer = [];
883
884
        $sqlType = $this->getSqlType($column->getType());
0 ignored issues
show
Bug introduced by
It seems like $column->getType() targeting Phinx\Db\Table\Column::getType() can also be of type object<Phinx\Util\Literal>; however, Phinx\Db\Adapter\OracleAdapter::getSqlType() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
885
886
        $buffer[] = strtoupper($sqlType['name']);
887
        // integers cant have limits in Oracle
888
        $noLimits = [
889
            static::PHINX_TYPE_INTEGER,
890
            static::PHINX_TYPE_BIG_INTEGER,
891
            static::PHINX_TYPE_FLOAT,
892
            static::PHINX_TYPE_UUID,
893
            static::PHINX_TYPE_BOOLEAN
894
        ];
895 View Code Duplication
        if (!in_array($column->getType(), $noLimits) && ($column->getLimit() || isset($sqlType['limit']))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
896
            $buffer[] = sprintf('(%s)', $column->getLimit() ?: $sqlType['limit']);
897
        }
898 View Code Duplication
        if ($column->getPrecision() && $column->getScale()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
899
            $buffer[] = '(' . $column->getPrecision() . ',' . $column->getScale() . ')';
900
        }
901
902 View Code Duplication
        if ($column->getDefault() === null && $column->isNull()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
903
            $buffer[] = ' DEFAULT NULL';
904
        } else {
905
            $buffer[] = $this->getDefaultValueDefinition($column->getDefault());
906
        }
907
908
        if ($setNullSql) {
909
            $buffer[] = $column->isNull() ? 'NULL' : 'NOT NULL';
910
        }
911
912
        return implode(' ', $buffer);
913
    }
914
915
    /**
916
     * Gets the Oracle Index Definition for an Index object.
917
     *
918
     * @param \Phinx\Db\Table\Index $index Index
919
     * @param string $tableName Table Name
920
     * @return string
921
     */
922
    protected function getIndexSqlDefinition(Index $index, $tableName)
923
    {
924
        if (is_string($index->getName())) {
925
            $indexName = $index->getName();
926 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
927
            $columnNames = $index->getColumns();
928
            if (is_string($columnNames)) {
929
                $columnNames = [$columnNames];
930
            }
931
            $indexName = sprintf('%s_%s', $tableName, implode('_', $columnNames));
932
        }
933
        $def = sprintf(
934
            "CREATE %s INDEX %s ON %s (%s)",
935
            ($index->getType() === Index::UNIQUE ? 'UNIQUE' : ''),
936
            $indexName,
937
            $this->quoteTableName($tableName),
938
            '"' . implode('","', $index->getColumns()) . '"'
939
        );
940
941
        return $def;
942
    }
943
944
    /**
945
     * Gets the Oracle Foreign Key Definition for an ForeignKey object.
946
     *
947
     * @param \Phinx\Db\Table\ForeignKey $foreignKey Foreign Key Object
948
     * @param string $tableName Table Name
949
     * @return string
950
     */
951
    protected function getForeignKeySqlDefinition(ForeignKey $foreignKey, $tableName)
952
    {
953
        $constraintName = $foreignKey->getConstraint() ?: $tableName . '_' . implode('_', $foreignKey->getColumns());
954
        $def = ' CONSTRAINT ' . $this->quoteColumnName(substr($constraintName, 0, 27));
955
        $def .= ' FOREIGN KEY ("' . implode('", "', $foreignKey->getColumns()) . '")';
956
        $def .= " REFERENCES {$this->quoteTableName($foreignKey->getReferencedTable()->getName())} 
957
        (\"" . implode('", "', $foreignKey->getReferencedColumns()) . '")';
958
        if ($foreignKey->getOnDelete() && $foreignKey->getOnDelete() != "NO ACTION") {
959
            $def .= " ON DELETE {$foreignKey->getOnDelete()}";
960
        }
961
        if ($foreignKey->getOnUpdate()) {
962
            $def .= " ON UPDATE {$foreignKey->getOnUpdate()}";
963
        }
964
965
        return $def;
966
    }
967
968
    /**
969
     * {@inheritdoc}
970
     */
971
    public function getColumnTypes()
972
    {
973
        return array_merge(parent::getColumnTypes(), ['filestream']);
974
    }
975
976
    /**
977
     * Records a migration being run.
978
     *
979
     * @param \Phinx\Migration\MigrationInterface $migration Migration
980
     * @param string $direction Direction
981
     * @param int $startTime Start Time
982
     * @param int $endTime End Time
983
     * @return \Phinx\Db\Adapter\AdapterInterface
984
     */
985
    public function migrated(\Phinx\Migration\MigrationInterface $migration, $direction, $startTime, $endTime)
986
    {
987
        $startTime = "TO_TIMESTAMP('$startTime', 'YYYY-MM-DD HH24:MI:SS')";
988
        $endTime = "TO_TIMESTAMP('$endTime', 'YYYY-MM-DD HH24:MI:SS')";
989
990 View Code Duplication
        if (strcasecmp($direction, MigrationInterface::UP) === 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
991
            // up
992
            $sql = sprintf(
993
                "INSERT INTO \"%s\" (%s, %s, %s, %s, %s) VALUES ('%s', '%s', %s, %s, %s)",
994
                $this->getSchemaTableName(),
995
                $this->quoteColumnName('version'),
996
                $this->quoteColumnName('migration_name'),
997
                $this->quoteColumnName('start_time'),
998
                $this->quoteColumnName('end_time'),
999
                $this->quoteColumnName('breakpoint'),
1000
                $migration->getVersion(),
1001
                substr($migration->getName(), 0, 100),
1002
                $startTime,
1003
                $endTime,
1004
                $this->castToBool(false)
1005
            );
1006
1007
            $this->execute($sql);
1008
        } else {
1009
            // down
1010
            $sql = sprintf(
1011
                "DELETE FROM \"%s\" WHERE %s = '%s'",
1012
                $this->getSchemaTableName(),
1013
                $this->quoteColumnName('version'),
1014
                $migration->getVersion()
1015
            );
1016
1017
            $this->execute($sql);
1018
        }
1019
1020
        return $this;
1021
    }
1022
1023
    /**
1024
     * {@inheritdoc}
1025
     */
1026
    public function bulkinsert(Table $table, $rows)
1027
    {
1028
        $sql = "INSERT ALL ";
1029
1030
        $vals = [];
1031
        $tableName = $table->getName();
1032
        $primaryKeyColumn = current($this->getForeignKeys($tableName, 'P'));
1033
        $sequenceNextVal = $this->getNextValSequence('SQ_' . $tableName);
1034
//        buscar sequence e primary key padr�o para incrementar PK com a SEQUENCE.NEXTVAL
1035
1036
        foreach ($rows as $key => $row) {
1037
            $pk = ($sequenceNextVal + $key);
1038
            $row[$primaryKeyColumn['COLUMNS'][0]] = (int)$pk;
1039
1040
            $sql .= sprintf(
1041
                "INTO %s ",
1042
                $this->quoteTableName($tableName)
1043
            );
1044
1045
            $keys = array_keys($row);
1046
            $sql .= "(" . implode(', ', array_map([$this, 'quoteColumnName'], $keys)) . ") VALUES";
1047
1048
            foreach ($row as $v) {
1049
                $vals[] = $v;
1050
            }
1051
1052
            $count_keys = count($keys);
1053
            $query = " (" . implode(', ', array_fill(0, $count_keys, '?')) . ") ";
1054
1055
            $queries = array_fill(0, 1, $query);
1056
            $sql .= implode(',', $queries);
1057
        }
1058
        $sql .= "SELECT 1 FROM DUAL";
1059
        $stmt = $this->getConnection()->prepare($sql);
1060
        $stmt->execute($vals);
1061
    }
1062
1063
    /**
1064
     * Get Next Auto Increment Value Sequence
1065
     *
1066
     *
1067
     * @param string $sequence Sequence Name
1068
     * @return int
1069
     */
1070
    protected function getNextValSequence($sequence)
1071
    {
1072
        $sql = "SELECT %s.NEXTVAL FROM DUAL";
1073
        $rows = $this->fetchAll(sprintf($sql, $sequence));
1074
1075
        return $rows[0]['NEXTVAL'];
1076
    }
1077
1078
    /**
1079
     * {@inheritdoc}
1080
     */
1081 View Code Duplication
    public function getVersionLog()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1082
    {
1083
        $result = [];
1084
1085
        switch ($this->options['version_order']) {
1086
            case \Phinx\Config\Config::VERSION_ORDER_CREATION_TIME:
1087
                $orderBy = '"version" ASC';
1088
                break;
1089
            case \Phinx\Config\Config::VERSION_ORDER_EXECUTION_TIME:
1090
                $orderBy = '"start_time" ASC, "version" ASC';
1091
                break;
1092
            default:
1093
                throw new \RuntimeException('Invalid version_order configuration option');
1094
        }
1095
1096
        $rows = $this->fetchAll(sprintf('SELECT * FROM %s ORDER BY %s', $this->quoteColumnName(
1097
            $this->getSchemaTableName()
1098
        ), $orderBy));
1099
        foreach ($rows as $version) {
1100
            $result[$version['version']] = $version;
1101
        }
1102
1103
        return $result;
1104
    }
1105
}
1106