Test Failed
Pull Request — develop (#380)
by Felipe
03:38
created

ColumnTrait::renameColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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