1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* PHPPgAdmin v6.0.0-beta.48 |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace PHPPgAdmin\Database\Traits; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Common trait for tables manipulation. |
11
|
|
|
*/ |
12
|
|
|
trait SchemaTrait |
13
|
|
|
{ |
14
|
|
|
// Schema functons |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Return all schemas in the current database. |
18
|
|
|
* |
19
|
|
|
* @return \PHPPgAdmin\ADORecordSet All schemas, sorted alphabetically |
20
|
|
|
*/ |
21
|
|
View Code Duplication |
public function getSchemas() |
|
|
|
|
22
|
|
|
{ |
23
|
|
|
$conf = $this->conf; |
|
|
|
|
24
|
|
|
|
25
|
|
|
if (!$conf['show_system']) { |
26
|
|
|
$where = "WHERE nspname NOT LIKE 'pg@_%' ESCAPE '@' AND nspname != 'information_schema'"; |
27
|
|
|
} else { |
28
|
|
|
$where = "WHERE nspname !~ '^pg_t(emp_[0-9]+|oast)$'"; |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
$sql = " |
32
|
|
|
SELECT pn.nspname, |
33
|
|
|
pu.rolname AS nspowner, |
34
|
|
|
pg_catalog.obj_description(pn.oid, 'pg_namespace') AS nspcomment, |
35
|
|
|
pg_size_pretty(SUM(pg_total_relation_size(pg_class.oid))) as schema_size |
36
|
|
|
FROM pg_catalog.pg_namespace pn |
37
|
|
|
LEFT JOIN pg_catalog.pg_class ON relnamespace = pn.oid |
38
|
|
|
LEFT JOIN pg_catalog.pg_roles pu ON (pn.nspowner = pu.oid) |
39
|
|
|
{$where} |
40
|
|
|
GROUP BY pn.nspname, pu.rolname, pg_catalog.obj_description(pn.oid, 'pg_namespace') |
41
|
|
|
ORDER BY nspname"; |
42
|
|
|
|
43
|
|
|
return $this->selectSet($sql); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Sets the current working schema. Will also set Class variable. |
48
|
|
|
* |
49
|
|
|
* @param string $schema The the name of the schema to work in |
50
|
|
|
* |
51
|
|
|
* @return int 0 if operation was successful |
52
|
|
|
*/ |
53
|
|
|
public function setSchema($schema) |
54
|
|
|
{ |
55
|
|
|
// Get the current schema search path, including 'pg_catalog'. |
56
|
|
|
$search_path = $this->getSearchPath(); |
57
|
|
|
// Prepend $schema to search path |
58
|
|
|
array_unshift($search_path, $schema); |
59
|
|
|
$status = $this->setSearchPath($search_path); |
60
|
|
|
|
61
|
|
|
if ($status == 0) { |
62
|
|
|
$this->_schema = $schema; |
|
|
|
|
63
|
|
|
|
64
|
|
|
return 0; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
return $status; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Return the current schema search path. |
72
|
|
|
* |
73
|
|
|
* @return array array of schema names |
74
|
|
|
*/ |
75
|
|
|
public function getSearchPath() |
76
|
|
|
{ |
77
|
|
|
$sql = 'SELECT current_schemas(false) AS search_path'; |
78
|
|
|
|
79
|
|
|
$fetchMode = $this->conn->fetchMode; |
|
|
|
|
80
|
|
|
$this->conn->setFetchMode(\ADODB_FETCH_ASSOC); |
81
|
|
|
$search_path = $this->selectField($sql, 'search_path'); |
82
|
|
|
$this->conn->setFetchMode($fetchMode); |
83
|
|
|
|
84
|
|
|
return $this->phpArray($search_path); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Sets the current schema search path. |
89
|
|
|
* |
90
|
|
|
* @param mixed $paths An array of schemas in required search order |
91
|
|
|
* |
92
|
|
|
* @return int 0 if operation was successful |
93
|
|
|
*/ |
94
|
|
|
public function setSearchPath($paths) |
95
|
|
|
{ |
96
|
|
|
if (!is_array($paths)) { |
97
|
|
|
return -1; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
if (sizeof($paths) == 0) { |
101
|
|
|
return -2; |
102
|
|
|
} |
103
|
|
|
if (sizeof($paths) == 1 && $paths[0] == '') { |
104
|
|
|
// Need to handle empty paths in some cases |
105
|
|
|
$paths[0] = 'pg_catalog'; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
// Loop over all the paths to check that none are empty |
109
|
|
|
$temp = []; |
110
|
|
|
foreach ($paths as $schema) { |
111
|
|
|
if ($schema != '') { |
112
|
|
|
$temp[] = $schema; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
$this->fieldArrayClean($temp); |
116
|
|
|
|
117
|
|
|
$sql = 'SET SEARCH_PATH TO "'.implode('","', $temp).'"'; |
118
|
|
|
|
119
|
|
|
return $this->execute($sql); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Creates a new schema. |
124
|
|
|
* |
125
|
|
|
* @param string $schemaname The name of the schema to create |
126
|
|
|
* @param string $authorization (optional) The username to create the schema for |
127
|
|
|
* @param string $comment (optional) If omitted, defaults to nothing |
128
|
|
|
* |
129
|
|
|
* @return bool|int 0 success |
130
|
|
|
*/ |
131
|
|
|
public function createSchema($schemaname, $authorization = '', $comment = '') |
132
|
|
|
{ |
133
|
|
|
$this->fieldClean($schemaname); |
134
|
|
|
$this->fieldClean($authorization); |
135
|
|
|
|
136
|
|
|
$sql = "CREATE SCHEMA \"{$schemaname}\""; |
137
|
|
|
if ($authorization != '') { |
138
|
|
|
$sql .= " AUTHORIZATION \"{$authorization}\""; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
if ($comment != '') { |
142
|
|
|
$status = $this->beginTransaction(); |
143
|
|
|
if ($status != 0) { |
144
|
|
|
return -1; |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
// Create the new schema |
149
|
|
|
$status = $this->execute($sql); |
150
|
|
|
if ($status != 0) { |
151
|
|
|
$this->rollbackTransaction(); |
152
|
|
|
|
153
|
|
|
return -1; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
// Set the comment |
157
|
|
|
if ($comment != '') { |
158
|
|
|
$status = $this->setComment('SCHEMA', $schemaname, '', $comment); |
159
|
|
|
if ($status != 0) { |
160
|
|
|
$this->rollbackTransaction(); |
161
|
|
|
|
162
|
|
|
return -1; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
return $this->endTransaction(); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return 0; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Updates a schema. |
173
|
|
|
* |
174
|
|
|
* @param string $schemaname The name of the schema to drop |
175
|
|
|
* @param string $comment The new comment for this schema |
176
|
|
|
* @param string $name new name for this schema |
177
|
|
|
* @param string $owner The new owner for this schema |
178
|
|
|
* |
179
|
|
|
* @return bool|int 0 success |
180
|
|
|
*/ |
181
|
|
|
public function updateSchema($schemaname, $comment, $name, $owner) |
182
|
|
|
{ |
183
|
|
|
$this->fieldClean($schemaname); |
184
|
|
|
$this->fieldClean($name); |
185
|
|
|
$this->fieldClean($owner); |
186
|
|
|
|
187
|
|
|
$status = $this->beginTransaction(); |
188
|
|
|
if ($status != 0) { |
189
|
|
|
$this->rollbackTransaction(); |
190
|
|
|
|
191
|
|
|
return -1; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
$status = $this->setComment('SCHEMA', $schemaname, '', $comment); |
195
|
|
|
if ($status != 0) { |
196
|
|
|
$this->rollbackTransaction(); |
197
|
|
|
|
198
|
|
|
return -1; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
$schema_rs = $this->getSchemaByName($schemaname); |
202
|
|
|
/* Only if the owner change */ |
203
|
|
View Code Duplication |
if ($schema_rs->fields['ownername'] != $owner) { |
|
|
|
|
204
|
|
|
$sql = "ALTER SCHEMA \"{$schemaname}\" OWNER TO \"{$owner}\""; |
205
|
|
|
$status = $this->execute($sql); |
206
|
|
|
if ($status != 0) { |
207
|
|
|
$this->rollbackTransaction(); |
208
|
|
|
|
209
|
|
|
return -1; |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
// Only if the name has changed |
214
|
|
View Code Duplication |
if ($name != $schemaname) { |
|
|
|
|
215
|
|
|
$sql = "ALTER SCHEMA \"{$schemaname}\" RENAME TO \"{$name}\""; |
216
|
|
|
$status = $this->execute($sql); |
217
|
|
|
if ($status != 0) { |
218
|
|
|
$this->rollbackTransaction(); |
219
|
|
|
|
220
|
|
|
return -1; |
221
|
|
|
} |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
return $this->endTransaction(); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Return all information relating to a schema. |
229
|
|
|
* |
230
|
|
|
* @param string $schema The name of the schema |
231
|
|
|
* |
232
|
|
|
* @return \PHPPgAdmin\ADORecordSet Schema information |
233
|
|
|
*/ |
234
|
|
|
public function getSchemaByName($schema) |
235
|
|
|
{ |
236
|
|
|
$this->clean($schema); |
237
|
|
|
$sql = " |
238
|
|
|
SELECT nspname, nspowner, r.rolname AS ownername, nspacl, |
239
|
|
|
pg_catalog.obj_description(pn.oid, 'pg_namespace') as nspcomment |
240
|
|
|
FROM pg_catalog.pg_namespace pn |
241
|
|
|
LEFT JOIN pg_roles as r ON pn.nspowner = r.oid |
242
|
|
|
WHERE nspname='{$schema}'"; |
243
|
|
|
|
244
|
|
|
return $this->selectSet($sql); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
// Table functions |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Drops a schema. |
251
|
|
|
* |
252
|
|
|
* @param string $schemaname The name of the schema to drop |
253
|
|
|
* @param bool $cascade True to cascade drop, false to restrict |
254
|
|
|
* |
255
|
|
|
* @return int 0 if operation was successful |
256
|
|
|
*/ |
257
|
|
|
public function dropSchema($schemaname, $cascade) |
258
|
|
|
{ |
259
|
|
|
$this->fieldClean($schemaname); |
260
|
|
|
|
261
|
|
|
$sql = "DROP SCHEMA \"{$schemaname}\""; |
262
|
|
|
if ($cascade) { |
263
|
|
|
$sql .= ' CASCADE'; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
return $this->execute($sql); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
abstract public function fieldClean(&$str); |
|
|
|
|
270
|
|
|
|
271
|
|
|
abstract public function beginTransaction(); |
|
|
|
|
272
|
|
|
|
273
|
|
|
abstract public function rollbackTransaction(); |
|
|
|
|
274
|
|
|
|
275
|
|
|
abstract public function endTransaction(); |
|
|
|
|
276
|
|
|
|
277
|
|
|
abstract public function execute($sql); |
|
|
|
|
278
|
|
|
|
279
|
|
|
abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null); |
|
|
|
|
280
|
|
|
|
281
|
|
|
abstract public function selectSet($sql); |
|
|
|
|
282
|
|
|
|
283
|
|
|
abstract public function clean(&$str); |
|
|
|
|
284
|
|
|
|
285
|
|
|
abstract public function phpBool($parameter); |
|
|
|
|
286
|
|
|
|
287
|
|
|
abstract public function hasCreateTableLikeWithConstraints(); |
|
|
|
|
288
|
|
|
|
289
|
|
|
abstract public function hasCreateTableLikeWithIndexes(); |
|
|
|
|
290
|
|
|
|
291
|
|
|
abstract public function hasTablespaces(); |
|
|
|
|
292
|
|
|
|
293
|
|
|
abstract public function delete($table, $conditions, $schema = ''); |
|
|
|
|
294
|
|
|
|
295
|
|
|
abstract public function fieldArrayClean(&$arr); |
|
|
|
|
296
|
|
|
|
297
|
|
|
abstract public function hasCreateFieldWithConstraints(); |
|
|
|
|
298
|
|
|
|
299
|
|
|
abstract public function getAttributeNames($table, $atts); |
|
|
|
|
300
|
|
|
|
301
|
|
|
abstract public function selectField($sql, $field); |
|
|
|
|
302
|
|
|
|
303
|
|
|
abstract public function phpArray($dbarr); |
|
|
|
|
304
|
|
|
} |
305
|
|
|
|
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.