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

PostgresHandler::getSchema()   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 2
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, bool $restartIdentity = false): void
75
    {
76 12
        $query = "TRUNCATE TABLE {$this->driver->identifier($table->getFullName())}";
77 12
78
        if ($restartIdentity) {
79 10
            $query .= ' RESTART IDENTITY CASCADE';
80
        }
81
82
        $this->driver->execute($query);
83
    }
84
85 2
    /**
86
     * @psalm-param non-empty-string $table
87
     * @psalm-param non-empty-string $name
88 2
     */
89
    public function renameTable(string $table, string $name): void
90 2
    {
91 2
        // New table name should not contain a schema
92
        [, $name] = $this->driver->parseSchemaAndTable($name);
93
94
        parent::renameTable($table, $name);
95
    }
96 40
97
    /**
98
     * @throws SchemaException
99
     */
100
    public function alterColumn(
101 40
        AbstractTable $table,
102
        AbstractColumn $initial,
103
        AbstractColumn $column
104
    ): void {
105
        if (!$initial instanceof PostgresColumn || !$column instanceof PostgresColumn) {
106 40
            throw new SchemaException('Postgres handler can work only with Postgres columns');
107 18
        }
108
109
        //Rename is separate operation
110 18
        if ($column->getName() !== $initial->getName()) {
111
            $this->renameColumn($table, $initial, $column);
112
113
            //This call is required to correctly built set of alter operations
114 40
            $initial->setName($column->getName());
115 40
        }
116 12
117
        //Postgres columns should be altered using set of operations
118
        $operations = $column->alterOperations($this->driver, $initial);
119
        if (empty($operations)) {
120 28
            return;
121 28
        }
122 28
123 28
        //Postgres columns should be altered using set of operations
124
        $query = sprintf(
125
            'ALTER TABLE %s %s',
126 28
            $this->identify($table),
127 28
            trim(implode(', ', $operations), ', ')
128
        );
129
130
        $this->run($query);
131
    }
132 516
133
    public function enableForeignKeyConstraints(): void
134 516
    {
135
        $this->run('SET CONSTRAINTS ALL IMMEDIATE;');
136 516
    }
137
138
    public function disableForeignKeyConstraints(): void
139 516
    {
140
        $this->run('SET CONSTRAINTS ALL DEFERRED;');
141
    }
142 18
143
    /**
144
     * @psalm-param non-empty-string $statement
145
     */
146
    protected function run(string $statement, array $parameters = []): int
147 18
    {
148 18
        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...
149 18
            // invaliding primary key cache
150 18
            $this->driver->resetPrimaryKeys();
151 18
        }
152
153
        return parent::run($statement, $parameters);
154 18
    }
155 18
156
    private function renameColumn(
157
        AbstractTable $table,
158
        AbstractColumn $initial,
159
        AbstractColumn $column
160
    ): void {
161
        $statement = sprintf(
162
            'ALTER TABLE %s RENAME COLUMN %s TO %s',
163
            $this->identify($table),
164
            $this->identify($initial),
165
            $this->identify($column)
166
        );
167
168
        $this->run($statement);
169
    }
170
}
171