Issues (3)

src/Db/Database.php (1 issue)

Severity
1
<?php
2
3
namespace Lagdo\DbAdmin\Driver\PgSql\Db;
4
5
use Lagdo\DbAdmin\Driver\Entity\TableEntity;
6
use Lagdo\DbAdmin\Driver\Entity\RoutineEntity;
7
8
use Lagdo\DbAdmin\Driver\Db\Database as AbstractDatabase;
9
10
class Database extends AbstractDatabase
11
{
12
    use DatabaseTrait;
0 ignored issues
show
The trait Lagdo\DbAdmin\Driver\PgSql\Db\DatabaseTrait requires some properties which are not provided by Lagdo\DbAdmin\Driver\PgSql\Db\Database: $name, $dropped, $fields, $comment, $edited, $engine
Loading history...
13
14
    /**
15
     * PostgreSQL system schemas
16
     *
17
     * @var array
18
     */
19
    protected $systemSchemas = ['information_schema', 'pg_catalog', 'pg_temp_1', 'pg_toast', 'pg_toast_temp_1'];
20
21
    /**
22
     * @inheritDoc
23
     */
24
    public function createTable(TableEntity $tableAttrs)
25
    {
26
        $queries = $this->getQueries($tableAttrs);
27
        $columns = $this->getNewColumns($tableAttrs);
28
        $columns = array_merge($columns, $tableAttrs->foreign);
29
        array_unshift($queries, 'CREATE TABLE ' . $this->driver->escapeTableName($tableAttrs->name) .
30
            '(' . implode(', ', $columns) . ')');
31
        foreach ($queries as $query) {
32
            $this->driver->execute($query);
33
        }
34
        return true;
35
    }
36
37
    /**
38
     * @inheritDoc
39
     */
40
    public function alterTable(string $table, TableEntity $tableAttrs)
41
    {
42
        $queries = $this->getQueries($tableAttrs);
43
        $columns = $this->getColumnChanges($tableAttrs);
44
        if ($tableAttrs->name !== '' && $table !== $tableAttrs->name) {
45
            array_unshift($queries, 'ALTER TABLE ' . $this->driver->escapeTableName($table) .
46
                ' RENAME TO ' . $this->driver->escapeTableName($tableAttrs->name));
47
        }
48
        $columns = array_merge($columns, $tableAttrs->foreign);
49
        if (!empty($columns)) {
50
            array_unshift($queries, 'ALTER TABLE ' . $this->driver->escapeTableName($table) . ' ' . implode(', ', $columns));
51
        }
52
        // if ($tableAttrs->autoIncrement != '') {
53
        //     //! $queries[] = 'SELECT setval(pg_get_serial_sequence(' . $this->driver->quote($tableAttrs->name) . ', ), $tableAttrs->autoIncrement)';
54
        // }
55
        foreach ($queries as $query) {
56
            $this->driver->execute($query);
57
        }
58
        return true;
59
    }
60
61
    /**
62
     * @inheritDoc
63
     */
64
    public function alterIndexes(string $table, array $alter, array $drop)
65
    {
66
        $queries = [];
67
        $columns = [];
68
        foreach (array_reverse($drop) as $index) {
69
            if ($index->type === 'INDEX') {
70
                $queries[] = 'DROP INDEX ' . $this->driver->escapeId($index);
71
            } else {
72
                $columns[] = 'DROP CONSTRAINT ' . $this->driver->escapeId($index->name);
73
            }
74
        }
75
        foreach ($alter as $index) {
76
            if ($index->type === 'INDEX') {
77
                $queries[] = 'CREATE INDEX ' .
78
                    $this->driver->escapeId($index->name != '' ? $index->name : uniqid($table . '_')) .
79
                    ' ON ' . $this->driver->escapeTableName($table) . ' (' . implode(', ', $index->columns) . ')';
80
            } else {
81
                //! descending UNIQUE indexes results in syntax error
82
                $constraint = ($index->name != '' ? ' CONSTRAINT ' . $this->driver->escapeId($index->name) : '');
83
                $columns[] = "ADD$constraint " . ($index->type == 'PRIMARY' ? 'PRIMARY KEY' : $index->type) .
84
                    ' (' . implode(', ', $index->columns) . ')';
85
            }
86
        }
87
        if (!empty($columns)) {
88
            array_unshift($queries, 'ALTER TABLE ' . $this->driver->escapeTableName($table) . implode(', ', $columns));
89
        }
90
        foreach ($queries as $query) {
91
            $this->driver->execute($query);
92
        }
93
        return true;
94
    }
95
96
    /**
97
     * @inheritDoc
98
     */
99
    public function tables()
100
    {
101
        $query = 'SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = current_schema()';
102
        if ($this->driver->support('materializedview')) {
103
            $query .= " UNION ALL SELECT matviewname, 'MATERIALIZED VIEW' FROM pg_matviews WHERE schemaname = current_schema()";
104
        }
105
        $query .= ' ORDER BY 1';
106
        return $this->driver->keyValues($query);
107
    }
108
109
    /**
110
     * @inheritDoc
111
     */
112
    public function sequences()
113
    {
114
        // From db.inc.php
115
        $query = 'SELECT sequence_name FROM information_schema.sequences ' .
116
            'WHERE sequence_schema = selectedSchema() ORDER BY sequence_name';
117
        return $this->driver->values($query);
118
    }
119
120
    /**
121
     * @inheritDoc
122
     */
123
    public function countTables(array $databases)
124
    {
125
        $counts = [];
126
        $query = "SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('" .
127
            implode("','", $this->systemSchemas) . "')";
128
        foreach ($databases as $database) {
129
            $counts[$database] = 0;
130
            $connection = $this->driver->connect($database); // New connection
131
            if (!$connection) {
132
                continue;
133
            }
134
            $statement = $connection->query($query);
135
            if (is_object($statement) && ($row = $statement->fetchRow())) {
136
                $counts[$database] = intval($row[0]);
137
            }
138
        }
139
        return $counts;
140
    }
141
142
    /**
143
     * @inheritDoc
144
     */
145
    public function dropViews(array $views)
146
    {
147
        return $this->dropTables($views);
148
    }
149
150
    /**
151
     * @inheritDoc
152
     */
153
    public function dropTables(array $tables)
154
    {
155
        foreach ($tables as $table) {
156
            $status = $this->driver->tableStatus($table);
157
            if (!$this->driver->execute('DROP ' . strtoupper($status->engine) . ' ' . $this->driver->escapeTableName($table))) {
158
                return false;
159
            }
160
        }
161
        return true;
162
    }
163
164
    /**
165
     * @inheritDoc
166
     */
167
    public function schemas()
168
    {
169
        $query = "SELECT nspname FROM pg_namespace WHERE nspname NOT IN ('" .
170
            implode("','", $this->systemSchemas) . "') ORDER BY nspname";
171
        return $this->driver->values($query);
172
    }
173
174
    /**
175
     * @inheritDoc
176
     */
177
    public function routine(string $name, string $type)
178
    {
179
        $query = 'SELECT routine_definition AS definition, LOWER(external_language) AS language, * ' .
180
            'FROM information_schema.routines WHERE routine_schema = current_schema() ' .
181
            'AND specific_name = ' . $this->driver->quote($name);
182
        $rows = $this->driver->rows($query);
183
        $routines = $rows[0];
184
        $routines['returns'] = ['type' => $routines['type_udt_name']];
185
        $query = 'SELECT parameter_name AS field, data_type AS type, character_maximum_length AS length, ' .
186
            'parameter_mode AS inout FROM information_schema.parameters WHERE specific_schema = current_schema() ' .
187
            'AND specific_name = ' . $this->driver->quote($name) . ' ORDER BY ordinal_position';
188
        $routines['fields'] = $this->driver->rows($query);
189
        return $routines;
190
    }
191
192
    /**
193
     * @inheritDoc
194
     */
195
    public function routines()
196
    {
197
        $query = 'SELECT specific_name AS "SPECIFIC_NAME", routine_type AS "ROUTINE_TYPE", ' .
198
            'routine_name AS "ROUTINE_NAME", type_udt_name AS "DTD_IDENTIFIER" ' .
199
            'FROM information_schema.routines WHERE routine_schema = current_schema() ORDER BY SPECIFIC_NAME';
200
        $rows = $this->driver->rows($query);
201
        return array_map(function($row) {
202
            return new RoutineEntity($row['ROUTINE_NAME'], $row['SPECIFIC_NAME'], $row['ROUTINE_TYPE'], $row['DTD_IDENTIFIER']);
203
        }, $rows);
204
    }
205
206
    /**
207
     * @inheritDoc
208
     */
209
    public function routineId(string $name, array $row)
210
    {
211
        $routine = [];
212
        foreach ($row['fields'] as $field) {
213
            $routine[] = $field->type;
214
        }
215
        return $this->driver->escapeId($name) . '(' . implode(', ', $routine) . ')';
216
    }
217
}
218