Issues (217)

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

Severity
1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Database\Traits;
8
9
/**
10
 * Common trait for column manipulation.
11
 */
12
trait ColumnTrait
13
{
14
    /**
15
     * Add a new column to a table.
16
     *
17
     * @param string $table   The table to add to
18
     * @param string $column  The name of the new column
19
     * @param string $type    The type of the column
20
     * @param bool   $array   True if array type, false otherwise
21
     * @param int    $length  The optional size of the column (ie. 30 for varchar(30))
22
     * @param bool   $notnull True if NOT NULL, false otherwise
23
     * @param mixed  $default The default for the column.  '' for none.
24
     * @param string $comment comment for the column
25
     *
26
     * @return array first element is 0 on success, second element is sql sentence
27
     */
28
    public function addColumn($table, $column, $type, $array, $length, $notnull, $default, $comment)
29
    {
30
        $f_schema = $this->_schema;
31
        $this->fieldClean($f_schema);
32
        $this->fieldClean($table);
33
        $this->fieldClean($column);
34
        $this->clean($type);
35
        $this->clean($length);
36
37
        if ('' === $length) {
38
            $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" {$type}";
39
        } else {
40
            switch ($type) {
41
                // Have to account for weird placing of length for with/without
42
                // time zone types
43
                case 'timestamp with time zone':
44
                case 'timestamp without time zone':
45
                    $qual = \mb_substr($type, 9);
46
                    $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" timestamp({$length}){$qual}";
47
48
                    break;
49
                case 'time with time zone':
50
                case 'time without time zone':
51
                    $qual = \mb_substr($type, 4);
52
                    $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" time({$length}){$qual}";
53
54
                    break;
55
56
                default:
57
                    $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ADD COLUMN \"{$column}\" {$type}({$length})";
58
            }
59
        }
60
61
        // Add array qualifier, if requested
62
        if ($array) {
63
            $sql .= '[]';
64
        }
65
66
        // If we have advanced column adding, add the extra qualifiers
67
        if ($this->hasCreateFieldWithConstraints()) {
68
            // NOT NULL clause
69
            if ($notnull) {
70
                $sql .= ' NOT NULL';
71
            }
72
73
            // DEFAULT clause
74
            if ('' !== $default) {
75
                $sql .= ' DEFAULT ' . $default;
76
            }
77
        }
78
79
        $status = $this->beginTransaction();
80
81
        if (0 !== $status) {
82
            return [-1, $sql];
83
        }
84
85
        $status = $this->execute($sql);
86
87
        if (0 !== $status) {
88
            $this->rollbackTransaction();
89
90
            return [-1, $sql];
91
        }
92
93
        $status = $this->setComment('COLUMN', $column, $table, $comment);
94
95
        if (0 !== $status) {
96
            $this->rollbackTransaction();
97
98
            return [-1, $sql];
99
        }
100
101
        $status = $this->endTransaction();
102
103
        return [$status, $sql];
104
    }
105
106
    /**
107
     * Alters a column in a table.
108
     *
109
     * @param string $table      The table in which the column resides
110
     * @param string $column     The column to alter
111
     * @param string $name       The new name for the column
112
     * @param bool   $notnull    (boolean) True if not null, false otherwise
113
     * @param bool   $oldnotnull (boolean) True if column is already not null, false otherwise
114
     * @param mixed  $default    The new default for the column
115
     * @param mixed  $olddefault The old default for the column
116
     * @param string $type       The new type for the column
117
     * @param int    $length     The optional size of the column (ie. 30 for varchar(30))
118
     * @param bool   $array      True if array type, false otherwise
119
     * @param string $oldtype    The old type for the column
120
     * @param string $comment    Comment for the column
121
     *
122
     * @return array 0 success
123
     */
124
    public function alterColumn(
125
        $table,
126
        $column,
127
        $name,
128
        $notnull,
129
        $oldnotnull,
130
        $default,
131
        $olddefault,
132
        $type,
133
        $length,
134
        $array,
135
        $oldtype,
136
        $comment
137
    ) {
138
        // Begin transaction
139
        $status = $this->beginTransaction();
140
        $sql = '';
141
        $sqlrename = '';
142
143
        if (0 !== $status) {
144
            $this->rollbackTransaction();
145
146
            return [-6, $sql];
147
        }
148
149
        // Rename the column, if it has been changed
150
        if ($column !== $name) {
151
            [$status, $sqlrename] = $this->renameColumn($table, $column, $name);
152
153
            if (0 !== $status) {
154
                $this->rollbackTransaction();
155
156
                return [-4, $sql];
157
            }
158
        }
159
160
        $f_schema = $this->_schema;
161
        $this->fieldClean($f_schema);
162
        $this->fieldClean($name);
163
        $this->fieldClean($table);
164
        $this->fieldClean($column);
165
166
        $toAlter = [];
167
        // Create the command for changing nullability
168
        if ($notnull !== $oldnotnull) {
169
            $toAlter[] = "ALTER COLUMN \"{$name}\" " . ($notnull ? 'SET' : 'DROP') . ' NOT NULL';
170
        }
171
172
        // Add default, if it has changed
173
        if ($default !== $olddefault) {
174
            if ('' === $default) {
175
                $toAlter[] = "ALTER COLUMN \"{$name}\" DROP DEFAULT";
176
            } else {
177
                $toAlter[] = "ALTER COLUMN \"{$name}\" SET DEFAULT {$default}";
178
            }
179
        }
180
181
        // Add type, if it has changed
182
        if ('' === $length) {
0 ignored issues
show
The condition '' === $length is always false.
Loading history...
183
            $ftype = $type;
184
        } else {
185
            switch ($type) {
186
                // Have to account for weird placing of length for with/without
187
                // time zone types
188
                case 'timestamp with time zone':
189
                case 'timestamp without time zone':
190
                    $qual = \mb_substr($type, 9);
191
                    $ftype = "timestamp({$length}){$qual}";
192
193
                    break;
194
                case 'time with time zone':
195
                case 'time without time zone':
196
                    $qual = \mb_substr($type, 4);
197
                    $ftype = "time({$length}){$qual}";
198
199
                    break;
200
201
                default:
202
                    $ftype = "{$type}({$length})";
203
            }
204
        }
205
206
        // Add array qualifier, if requested
207
        if ($array) {
208
            $ftype .= '[]';
209
        }
210
211
        if ($ftype !== $oldtype) {
212
            $toAlter[] = "ALTER COLUMN \"{$name}\" TYPE {$ftype}";
213
        }
214
215
        // Attempt to process the batch alteration, if anything has been changed
216
        if (!empty($toAlter)) {
217
            // Initialise an empty SQL string
218
            $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" "
219
            . \implode(',', $toAlter);
220
221
            $status = $this->execute($sql);
222
223
            if (0 !== $status) {
224
                $this->rollbackTransaction();
225
226
                return [-1, $sql];
227
            }
228
        }
229
230
        // Update the comment on the column
231
        $status = $this->setComment('COLUMN', $name, $table, $comment);
232
233
        if (0 !== $status) {
234
            $this->rollbackTransaction();
235
236
            return [-5, $sql];
237
        }
238
239
        return [$this->endTransaction(), $sqlrename . '<br>' . $sql];
240
    }
241
242
    /**
243
     * Renames a column in a table.
244
     *
245
     * @param string $table   The table containing the column to be renamed
246
     * @param string $column  The column to be renamed
247
     * @param string $newName The new name for the column
248
     *
249
     * @return array [0 if operation was successful, sql of sentence]
250
     */
251
    public function renameColumn($table, $column, $newName)
252
    {
253
        $f_schema = $this->_schema;
254
        $this->fieldClean($f_schema);
255
        $this->fieldClean($table);
256
        $this->fieldClean($column);
257
        $this->fieldClean($newName);
258
259
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" RENAME COLUMN \"{$column}\" TO \"{$newName}\"";
260
261
        $status = $this->execute($sql);
262
263
        return [$status, $sql];
264
    }
265
266
    /**
267
     * Sets default value of a column.
268
     *
269
     * @param string $table   The table from which to drop
270
     * @param string $column  The column name to set
271
     * @param mixed  $default The new default value
272
     *
273
     * @return int|\PHPPgAdmin\ADORecordSet
274
     */
275
    public function setColumnDefault($table, $column, $default)
276
    {
277
        $f_schema = $this->_schema;
278
        $this->fieldClean($f_schema);
279
        $this->fieldClean($table);
280
        $this->fieldClean($column);
281
282
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" SET DEFAULT {$default}";
283
284
        return $this->execute($sql);
285
    }
286
287
    /**
288
     * Sets whether or not a column can contain NULLs.
289
     *
290
     * @param string $table  The table that contains the column
291
     * @param string $column The column to alter
292
     * @param bool   $state  True to set null, false to set not null
293
     *
294
     * @return int|\PHPPgAdmin\ADORecordSet
295
     */
296
    public function setColumnNull($table, $column, $state)
297
    {
298
        $f_schema = $this->_schema;
299
        $this->fieldClean($f_schema);
300
        $this->fieldClean($table);
301
        $this->fieldClean($column);
302
303
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" " . ($state ? 'DROP' : 'SET') . ' NOT NULL';
304
305
        return $this->execute($sql);
306
    }
307
308
    /**
309
     * Drops a column from a table.
310
     *
311
     * @param string $table   The table from which to drop a column
312
     * @param string $column  The column to be dropped
313
     * @param bool   $cascade True to cascade drop, false to restrict
314
     *
315
     * @return array [int status, string sql sentence]
316
     */
317
    public function dropColumn($table, $column, $cascade)
318
    {
319
        $f_schema = $this->_schema;
320
        $this->fieldClean($f_schema);
321
        $this->fieldClean($table);
322
        $this->fieldClean($column);
323
324
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" DROP COLUMN \"{$column}\"";
325
326
        if ($cascade) {
327
            $sql .= ' CASCADE';
328
        }
329
330
        $status = $this->execute($sql);
331
332
        return [$status, $sql];
333
    }
334
335
    /**
336
     * Drops default value of a column.
337
     *
338
     * @param string $table  The table from which to drop
339
     * @param string $column The column name to drop default
340
     *
341
     * @return int|\PHPPgAdmin\ADORecordSet
342
     */
343
    public function dropColumnDefault($table, $column)
344
    {
345
        $f_schema = $this->_schema;
346
        $this->fieldClean($f_schema);
347
        $this->fieldClean($table);
348
        $this->fieldClean($column);
349
350
        $sql = "ALTER TABLE \"{$f_schema}\".\"{$table}\" ALTER COLUMN \"{$column}\" DROP DEFAULT";
351
352
        return $this->execute($sql);
353
    }
354
355
    abstract public function fieldClean(&$str);
356
357
    abstract public function beginTransaction();
358
359
    abstract public function rollbackTransaction();
360
361
    abstract public function endTransaction();
362
363
    abstract public function execute($sql);
364
365
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
366
367
    abstract public function selectSet($sql);
368
369
    abstract public function clean(&$str);
370
371
    abstract public function phpBool($parameter);
372
373
    abstract public function hasCreateTableLikeWithConstraints();
374
375
    abstract public function hasCreateTableLikeWithIndexes();
376
377
    abstract public function hasTablespaces();
378
379
    abstract public function delete($table, $conditions, $schema = '');
380
381
    abstract public function fieldArrayClean(&$arr);
382
383
    abstract public function hasCreateFieldWithConstraints();
384
385
    abstract public function getAttributeNames($table, $atts);
386
}
387