Passed
Pull Request — 2.x (#130)
by Maxim
16:20
created

PostgresHandler::disableForeignKeyConstraints()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
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\Postgres;
13
14
use Cycle\Database\Driver\Handler;
15
use Cycle\Database\Driver\Postgres\Schema\PostgresColumn;
16
use Cycle\Database\Driver\Postgres\Schema\PostgresTable;
17
use Cycle\Database\Exception\SchemaException;
18
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...
19
use Cycle\Database\Schema\AbstractTable;
20
21
/**
22
 * @property PostgresDriver $driver
23
 */
24
class PostgresHandler extends Handler
25
{
26
    /**
27
     * @psalm-param non-empty-string $table
28
     */
29 522
    public function getSchema(string $table, string $prefix = null): AbstractTable
30
    {
31 522
        return new PostgresTable($this->driver, $table, $prefix ?? '');
32
    }
33
34 920
    public function getTableNames(string $prefix = ''): array
35
    {
36 920
        $query = "SELECT table_schema, table_name
37
            FROM information_schema.tables
38
            WHERE table_type = 'BASE TABLE'";
39
40 920
        if ($this->driver->shouldUseDefinedSchemas()) {
41 920
            $query .= " AND table_schema in ('" . implode("','", $this->driver->getSearchSchemas()) . "')";
42
        } else {
43
            $query .= " AND table_schema !~ '^pg_.*' AND table_schema != 'information_schema'";
44
        }
45
46 920
        $tables = [];
47 920
        foreach ($this->driver->query($query) as $row) {
48 478
            if ($prefix !== '' && !str_starts_with($row['table_name'], $prefix)) {
49 2
                continue;
50
            }
51
52 478
            $tables[] = $row['table_schema'] . '.' . $row['table_name'];
53
        }
54
55 920
        return $tables;
56
    }
57
58
    /**
59
     * @psalm-param non-empty-string $table
60
     */
61 534
    public function hasTable(string $table): bool
62
    {
63 534
        [$schema, $name] = $this->driver->parseSchemaAndTable($table);
64
65 534
        $query = "SELECT COUNT(table_name)
66
            FROM information_schema.tables
67
            WHERE table_schema = ?
68
            AND table_type = 'BASE TABLE'
69
            AND table_name = ?";
70
71 534
        return (bool)$this->driver->query($query, [$schema, $name])->fetchColumn();
72
    }
73
74 12
    public function eraseTable(AbstractTable $table): void
75
    {
76 12
        $this->driver->execute(
77 12
            "TRUNCATE TABLE {$this->driver->identifier($table->getFullName())}"
78
        );
79 10
    }
80
81
    /**
82
     * @psalm-param non-empty-string $table
83
     * @psalm-param non-empty-string $name
84
     */
85 2
    public function renameTable(string $table, string $name): void
86
    {
87
        // New table name should not contain a schema
88 2
        [, $name] = $this->driver->parseSchemaAndTable($name);
89
90 2
        parent::renameTable($table, $name);
91 2
    }
92
93
    /**
94
     * @throws SchemaException
95
     */
96 40
    public function alterColumn(
97
        AbstractTable $table,
98
        AbstractColumn $initial,
99
        AbstractColumn $column
100
    ): void {
101 40
        if (!$initial instanceof PostgresColumn || !$column instanceof PostgresColumn) {
102
            throw new SchemaException('Postgres handler can work only with Postgres columns');
103
        }
104
105
        //Rename is separate operation
106 40
        if ($column->getName() !== $initial->getName()) {
107 18
            $this->renameColumn($table, $initial, $column);
108
109
            //This call is required to correctly built set of alter operations
110 18
            $initial->setName($column->getName());
111
        }
112
113
        //Postgres columns should be altered using set of operations
114 40
        $operations = $column->alterOperations($this->driver, $initial);
115 40
        if (empty($operations)) {
116 12
            return;
117
        }
118
119
        //Postgres columns should be altered using set of operations
120 28
        $query = sprintf(
121 28
            'ALTER TABLE %s %s',
122 28
            $this->identify($table),
123 28
            trim(implode(', ', $operations), ', ')
124
        );
125
126 28
        $this->run($query);
127 28
    }
128
129
    public function enableForeignKeyConstraints(): void
130
    {
131
        $this->run('SET CONSTRAINTS ALL IMMEDIATE;');
132 516
    }
133
134 516
    public function disableForeignKeyConstraints(): void
135
    {
136 516
        $this->run('SET CONSTRAINTS ALL DEFERRED;');
137
    }
138
139 516
    /**
140
     * @psalm-param non-empty-string $statement
141
     */
142 18
    protected function run(string $statement, array $parameters = []): int
143
    {
144
        if ($this->driver instanceof PostgresDriver) {
0 ignored issues
show
introduced by
$this->driver is always a sub-type of Cycle\Database\Driver\Postgres\PostgresDriver.
Loading history...
145
            // invaliding primary key cache
146
            $this->driver->resetPrimaryKeys();
147 18
        }
148 18
149 18
        return parent::run($statement, $parameters);
150 18
    }
151 18
152
    private function renameColumn(
153
        AbstractTable $table,
154 18
        AbstractColumn $initial,
155 18
        AbstractColumn $column
156
    ): void {
157
        $statement = sprintf(
158
            'ALTER TABLE %s RENAME COLUMN %s TO %s',
159
            $this->identify($table),
160
            $this->identify($initial),
161
            $this->identify($column)
162
        );
163
164
        $this->run($statement);
165
    }
166
}
167