Passed
Push — 2.x ( d36d3c...04f7c3 )
by Aleksei
19:00
created

MySQLHandler::enableForeignKeyConstraints()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of Cycle ORM package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\Database\Driver\MySQL;
13
14
use PDO;
15
use Cycle\Database\Driver\Handler;
16
use Cycle\Database\Driver\MySQL\Exception\MySQLException;
17
use Cycle\Database\Driver\MySQL\Schema\MySQLTable;
18
use Cycle\Database\Exception\SchemaException;
19
use Cycle\Database\Schema\AbstractColumn;
0 ignored issues
show
Bug introduced by
The type Cycle\Database\Schema\AbstractColumn was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use Cycle\Database\Schema\AbstractForeignKey;
21
use Cycle\Database\Schema\AbstractIndex;
22
use Cycle\Database\Schema\AbstractTable;
23
24
class MySQLHandler extends Handler
25
{
26
    /**
27
     * @psalm-param non-empty-string $table
28
     */
29 484
    public function getSchema(string $table, string $prefix = null): AbstractTable
30
    {
31 484
        return new MySQLTable($this->driver, $table, $prefix ?? '');
0 ignored issues
show
Bug introduced by
It seems like $this->driver can also be of type null; however, parameter $driver of Cycle\Database\Driver\My...SQLTable::__construct() does only seem to accept Cycle\Database\Driver\DriverInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

31
        return new MySQLTable(/** @scrutinizer ignore-type */ $this->driver, $table, $prefix ?? '');
Loading history...
32
    }
33
34 906
    public function getTableNames(string $prefix = ''): array
35
    {
36 906
        $result = [];
37 906
        foreach ($this->driver->query('SHOW TABLES')->fetchAll(PDO::FETCH_NUM) as $row) {
0 ignored issues
show
Bug introduced by
The method query() does not exist on null. ( Ignorable by Annotation )

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

37
        foreach ($this->driver->/** @scrutinizer ignore-call */ query('SHOW TABLES')->fetchAll(PDO::FETCH_NUM) as $row) {

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...
38 446
            if ($prefix !== '' && !str_starts_with($row[0], $prefix)) {
39 2
                continue;
40
            }
41
42 446
            $result[] = $row[0];
43
        }
44
45 906
        return $result;
46
    }
47
48
    /**
49
     * @psalm-param non-empty-string $table
50
     */
51 484
    public function hasTable(string $table): bool
52
    {
53 484
        $query = 'SELECT COUNT(*) FROM `information_schema`.`tables` WHERE `table_schema` = ? AND `table_name` = ?';
54
55 484
        return (bool)$this->driver->query(
56
            $query,
57 484
            [$this->driver->getSource(), $table]
0 ignored issues
show
Bug introduced by
The method getSource() does not exist on Cycle\Database\Driver\DriverInterface. It seems like you code against a sub-type of Cycle\Database\Driver\DriverInterface such as Cycle\Database\Driver\Driver. ( Ignorable by Annotation )

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

57
            [$this->driver->/** @scrutinizer ignore-call */ getSource(), $table]
Loading history...
58 484
        )->fetchColumn();
59
    }
60
61 4
    public function eraseTable(AbstractTable $table): void
62
    {
63 4
        $this->driver->execute(
64 4
            "TRUNCATE TABLE {$this->driver->identifier($table->getFullName())}"
0 ignored issues
show
Bug introduced by
The method identifier() does not exist on Cycle\Database\Driver\DriverInterface. It seems like you code against a sub-type of Cycle\Database\Driver\DriverInterface such as Cycle\Database\Driver\Driver. ( Ignorable by Annotation )

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

64
            "TRUNCATE TABLE {$this->driver->/** @scrutinizer ignore-call */ identifier($table->getFullName())}"
Loading history...
65
        );
66 2
    }
67
68 38
    public function alterColumn(
69
        AbstractTable $table,
70
        AbstractColumn $initial,
71
        AbstractColumn $column
72
    ): void {
73 38
        $foreignBackup = [];
74 38
        foreach ($table->getForeignKeys() as $foreign) {
75 2
            if ($column->getName() === $foreign->getColumns()) {
76
                $foreignBackup[] = $foreign;
77
                $this->dropForeignKey($table, $foreign);
78
            }
79
        }
80
81 38
        $this->run(
82 38
            "ALTER TABLE {$this->identify($table)}
83 38
                    CHANGE {$this->identify($initial)} {$column->sqlStatement($this->driver)}"
84
        );
85
86
        //Restoring FKs
87 38
        foreach ($foreignBackup as $foreign) {
88
            $this->createForeignKey($table, $foreign);
89
        }
90 38
    }
91
92 10
    public function dropIndex(AbstractTable $table, AbstractIndex $index): void
93
    {
94 10
        $this->run(
95 10
            "DROP INDEX {$this->identify($index)} ON {$this->identify($table)}"
96
        );
97 10
    }
98
99 2
    public function alterIndex(AbstractTable $table, AbstractIndex $initial, AbstractIndex $index): void
100
    {
101 2
        $this->run(
102 2
            "ALTER TABLE {$this->identify($table)}
103 2
                    DROP INDEX  {$this->identify($initial)},
104 2
                    ADD {$index->sqlStatement($this->driver, false)}"
0 ignored issues
show
Bug introduced by
It seems like $this->driver can also be of type null; however, parameter $driver of Cycle\Database\Schema\Ab...ctIndex::sqlStatement() does only seem to accept Cycle\Database\Driver\DriverInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

104
                    ADD {$index->sqlStatement(/** @scrutinizer ignore-type */ $this->driver, false)}"
Loading history...
105
        );
106 2
    }
107
108 56
    public function dropForeignKey(AbstractTable $table, AbstractForeignKey $foreignKey): void
109
    {
110 56
        $this->run(
111 56
            "ALTER TABLE {$this->identify($table)} DROP FOREIGN KEY {$this->identify($foreignKey)}"
112
        );
113 56
    }
114
115
    public function enableForeignKeyConstraints(): void
116
    {
117
        $this->run('SET FOREIGN_KEY_CHECKS=1;');
118
    }
119
120 478
    public function disableForeignKeyConstraints(): void
121
    {
122 478
        $this->run('SET FOREIGN_KEY_CHECKS=0;');
123
    }
124 478
125
    /**
126
     * Get statement needed to create table.
127
     *
128
     * @throws SchemaException
129
     */
130 478
    protected function createStatement(AbstractTable $table): string
131
    {
132
        $table instanceof MySQLTable or throw new SchemaException('MySQLHandler can process only MySQL tables');
133 478
134
        return parent::createStatement($table) . " ENGINE {$table->getEngine()}";
0 ignored issues
show
Bug introduced by
The method getEngine() does not exist on Cycle\Database\Schema\AbstractTable. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

134
        return parent::createStatement($table) . " ENGINE {$table->/** @scrutinizer ignore-call */ getEngine()}";
Loading history...
135 478
    }
136
137
    /**
138
     * @throws MySQLException
139 4
     */
140 4
    protected function assertValid(AbstractColumn $column): void
141
    {
142
        if (
143 474
            $column->getDefaultValue() !== null
144
            && \in_array(
145
                $column->getAbstractType(),
146
                ['text', 'tinyText', 'longText', 'blob', 'tinyBlob', 'longBlob', 'json']
147
            )
148
        ) {
149
            throw new MySQLException(
150
                "Column {$column} of type text/blob/json can not have non empty default value"
151
            );
152
        }
153
    }
154
}
155