Issues (217)

src/database/databasetraits/ViewTrait.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Database\Traits;
8
9
/**
10
 * Common trait for views manipulation.
11
 */
12
trait ViewTrait
13
{
14
    /**
15
     * Returns a list of all views in the database.
16
     *
17
     * @return int|\PHPPgAdmin\ADORecordSet
18
     */
19
    public function getViews()
20
    {
21
        $c_schema = $this->_schema;
22
        $this->clean($c_schema);
23
        $sql = "
24
			SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
25
				pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
26
			FROM pg_catalog.pg_class c
27
				LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace)
28
			WHERE (n.nspname='{$c_schema}') AND (c.relkind = 'v'::\"char\")
29
			ORDER BY relname";
30
31
        return $this->selectSet($sql);
32
    }
33
34
    /**
35
     * Returns a list of all materialized views in the database.
36
     *
37
     * @return int|\PHPPgAdmin\ADORecordSet
38
     */
39
    public function getMaterializedViews()
40
    {
41
        $c_schema = $this->_schema;
42
        $this->clean($c_schema);
43
        $sql = "
44
			SELECT c.relname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
45
				pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment
46
			FROM pg_catalog.pg_class c
47
				LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace)
48
			WHERE (n.nspname='{$c_schema}') AND (c.relkind = 'm'::\"char\")
49
			ORDER BY relname";
50
51
        return $this->selectSet($sql);
52
    }
53
54
    /**
55
     * Updates a view.
56
     *
57
     * @param string $viewname     The name fo the view to update
58
     * @param string $definition   The new definition for the view
59
     * @param string $comment
60
     * @param bool   $materialized tells if it's a materialized view or not
61
     *
62
     * @return bool|int 0 success
63
     */
64
    public function setView($viewname, $definition, $comment, $materialized = false)
65
    {
66
        return $this->createView($viewname, $definition, true, $comment, $materialized);
67
    }
68
69
    /**
70
     * Creates a new view.
71
     *
72
     * @param string $viewname     The name of the view to create
73
     * @param string $definition   The definition for the new view
74
     * @param bool   $replace      True to replace the view, false otherwise
75
     * @param string $comment
76
     * @param bool   $materialized tells if it's a materialized view
77
     *
78
     * @return bool|int 0 success
79
     */
80
    public function createView($viewname, $definition, $replace, $comment, $materialized = false)
81
    {
82
        $status = $this->beginTransaction();
83
84
        if (0 !== $status) {
85
            return -1;
86
        }
87
88
        $f_schema = $this->_schema;
89
        $this->fieldClean($f_schema);
90
        $this->fieldClean($viewname);
91
92
        // Note: $definition not cleaned
93
94
        $sql = 'CREATE ';
95
96
        $sql .= $replace ? ' OR REPLACE ' : ' ';
97
98
        $obj_type = $materialized ? ' MATERIALIZED VIEW ' : ' VIEW ';
99
100
        $sql .= $obj_type . " \"{$f_schema}\".\"{$viewname}\" AS {$definition}";
101
102
        $status = $this->execute($sql);
103
104
        if ($status) {
105
            $this->rollbackTransaction();
106
107
            return -1;
108
        }
109
110
        if ('' !== $comment) {
111
            $status = $this->setComment($obj_type, $viewname, '', $comment);
112
113
            if ($status) {
114
                $this->rollbackTransaction();
115
116
                return -1;
117
            }
118
        }
119
120
        return $this->endTransaction();
121
    }
122
123
    /**
124
     * Alter view properties.
125
     *
126
     * @param string $view    The name of the view
127
     * @param string $name    The new name for the view
128
     * @param string $owner   The new owner for the view
129
     * @param string $schema  The new schema for the view
130
     * @param string $comment The comment on the view
131
     *
132
     * @return bool|int 0 success
133
     */
134
    public function alterView($view, $name, $owner, $schema, $comment)
135
    {
136
        $data = $this->getView($view);
137
138
        if (1 !== $data->recordCount()) {
139
            return -2;
140
        }
141
142
        $status = $this->beginTransaction();
143
144
        if (0 !== $status) {
145
            $this->rollbackTransaction();
146
147
            return -1;
148
        }
149
150
        $status = $this->_alterView($data, $name, $owner, $schema, $comment);
0 ignored issues
show
It seems like $data can also be of type integer; however, parameter $vwrs of PHPPgAdmin\Database\Traits\ViewTrait::_alterView() does only seem to accept PHPPgAdmin\ADORecordSet, 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

150
        $status = $this->_alterView(/** @scrutinizer ignore-type */ $data, $name, $owner, $schema, $comment);
Loading history...
151
152
        if (0 !== $status) {
153
            $this->rollbackTransaction();
154
155
            return $status;
156
        }
157
158
        return $this->endTransaction();
159
    }
160
161
    /**
162
     * Returns all details for a particular view or materialized view.
163
     *
164
     * @param string $view The name of the view or materialized to retrieve
165
     *
166
     * @return int|\PHPPgAdmin\ADORecordSet
167
     */
168
    public function getView($view)
169
    {
170
        $c_schema = $this->_schema;
171
        $this->clean($c_schema);
172
        $this->clean($view);
173
174
        $sql = "
175
			SELECT c.relname, n.nspname, pg_catalog.pg_get_userbyid(c.relowner) AS relowner,
176
				pg_catalog.pg_get_viewdef(c.oid, true) AS vwdefinition,
177
				pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment,
178
                c.relkind
179
			FROM pg_catalog.pg_class c
180
				LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace)
181
			WHERE (c.relname = '{$view}') AND n.nspname='{$c_schema}'";
182
183
        return $this->selectSet($sql);
184
    }
185
186
    /**
187
     * Alter a view's owner.
188
     *
189
     * @param \PHPPgAdmin\ADORecordSet $vwrs  The view recordSet returned by getView()
190
     * @param null|string              $owner
191
     *
192
     * @return int|\PHPPgAdmin\ADORecordSet
193
     *
194
     * @internal param  $name new view's owner
195
     */
196
    public function alterViewOwner($vwrs, $owner = null)
197
    {
198
        $type = ('m' === $vwrs->fields['relkind']) ? 'MATERIALIZED VIEW' : 'VIEW';
199
        /* $vwrs and $owner are cleaned in _alterView */
200
        if ((!empty($owner)) && ($vwrs->fields['relowner'] !== $owner)) {
201
            $f_schema = $this->_schema;
202
            $this->fieldClean($f_schema);
203
            // If owner has been changed, then do the alteration.  We are
204
            // careful to avoid this generally as changing owner is a
205
            // superuser only function.
206
            $sql = "ALTER {$type} \"{$f_schema}\".\"{$vwrs->fields['relname']}\" OWNER TO \"{$owner}\"";
207
208
            return $this->execute($sql);
209
        }
210
211
        return 0;
212
    }
213
214
    /**
215
     * Rename a view.
216
     *
217
     * @param \PHPPgAdmin\ADORecordSet $vwrs The view recordSet returned by getView()
218
     * @param string                   $name The new view's name
219
     *
220
     * @return int|\PHPPgAdmin\ADORecordSet
221
     */
222
    public function alterViewName($vwrs, $name)
223
    {
224
        $type = ('m' === $vwrs->fields['relkind']) ? 'MATERIALIZED VIEW' : 'VIEW';
225
        // Rename (only if name has changed)
226
        /* $vwrs and $name are cleaned in _alterView */
227
        if (!empty($name) && ($name !== $vwrs->fields['relname'])) {
228
            $f_schema = $this->_schema;
229
            $this->fieldClean($f_schema);
230
            $sql = "ALTER {$type} \"{$f_schema}\".\"{$vwrs->fields['relname']}\" RENAME TO \"{$name}\"";
231
            $status = $this->execute($sql);
232
233
            if (0 === $status) {
234
                $vwrs->fields['relname'] = $name;
235
            } else {
236
                return $status;
237
            }
238
        }
239
240
        return 0;
241
    }
242
243
    /**
244
     * Alter a view's schema.
245
     *
246
     * @param \PHPPgAdmin\ADORecordSet $vwrs   The view recordSet returned by getView()
247
     * @param string                   $schema
248
     *
249
     * @return int|\PHPPgAdmin\ADORecordSet
250
     *
251
     * @internal param The $name new view's schema
252
     */
253
    public function alterViewSchema($vwrs, $schema)
254
    {
255
        $type = ('m' === $vwrs->fields['relkind']) ? 'MATERIALIZED VIEW' : 'VIEW';
256
257
        /* $vwrs and $schema are cleaned in _alterView */
258
        if (!empty($schema) && ($vwrs->fields['nspname'] !== $schema)) {
259
            $f_schema = $this->_schema;
260
            $this->fieldClean($f_schema);
261
            // If tablespace has been changed, then do the alteration.  We
262
            // don't want to do this unnecessarily.
263
            $sql = "ALTER {$type} \"{$f_schema}\".\"{$vwrs->fields['relname']}\" SET SCHEMA \"{$schema}\"";
264
265
            return $this->execute($sql);
266
        }
267
268
        return 0;
269
    }
270
271
    /**
272
     * Drops a view.
273
     *
274
     * @param string $viewname The name of the view to drop
275
     * @param string $cascade  True to cascade drop, false to restrict
276
     *
277
     * @return int|\PHPPgAdmin\ADORecordSet
278
     */
279
    public function dropView($viewname, $cascade)
280
    {
281
        $vwrs = $this->getView($viewname);
282
        $type = ('m' === $vwrs->fields['relkind']) ? 'MATERIALIZED VIEW' : 'VIEW';
283
284
        $f_schema = $this->_schema;
285
        $this->fieldClean($f_schema);
286
        $this->fieldClean($viewname);
287
288
        $sql = "DROP {$type} \"{$f_schema}\".\"{$viewname}\"";
289
290
        if ($cascade) {
291
            $sql .= ' CASCADE';
292
        }
293
294
        return $this->execute($sql);
295
    }
296
297
    abstract public function fieldClean(&$str);
298
299
    abstract public function beginTransaction();
300
301
    abstract public function rollbackTransaction();
302
303
    abstract public function endTransaction();
304
305
    abstract public function execute($sql);
306
307
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
308
309
    abstract public function selectSet($sql);
310
311
    abstract public function clean(&$str);
312
313
    abstract public function fieldArrayClean(&$arr);
314
315
    /**
316
     * Protected method which alter a view
317
     * SHOULDN'T BE CALLED OUTSIDE OF A TRANSACTION.
318
     *
319
     * @param \PHPPgAdmin\ADORecordSet $vwrs    The view recordSet returned by getView()
320
     * @param string                   $name    The new name for the view
321
     * @param string                   $owner   The new owner for the view
322
     * @param string                   $schema  Schema name
323
     * @param string                   $comment The comment on the view
324
     *
325
     * @return int 0 success
326
     */
327
    protected function _alterView($vwrs, $name, $owner, $schema, $comment)
328
    {
329
        $this->fieldArrayClean($vwrs->fields);
330
331
        $type = ('m' === $vwrs->fields['relkind']) ? 'MATERIALIZED VIEW' : 'VIEW';
332
        // Comment
333
334
        if (0 !== $this->setComment($type, $vwrs->fields['relname'], '', $comment)) {
335
            return -4;
336
        }
337
338
        // Owner
339
        $this->fieldClean($owner);
340
        $status = $this->alterViewOwner($vwrs, $owner);
341
342
        if (0 !== $status) {
343
            return -5;
344
        }
345
346
        // Rename
347
        $this->fieldClean($name);
348
        $status = $this->alterViewName($vwrs, $name);
349
350
        if (0 !== $status) {
351
            return -3;
352
        }
353
354
        // Schema
355
        $this->fieldClean($schema);
356
        $status = $this->alterViewSchema($vwrs, $schema);
357
358
        if (0 !== $status) {
359
            return -6;
360
        }
361
362
        return 0;
363
    }
364
}
365