TypeTrait::createCompositeType()   F
last analyzed

Complexity

Conditions 21
Paths 739

Size

Total Lines 117
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 65
c 0
b 0
f 0
nc 739
nop 8
dl 0
loc 117
rs 0.3625

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Database\Traits;
8
9
/**
10
 * Common trait for types manipulation.
11
 */
12
trait TypeTrait
13
{
14
    /**
15
     * Formats a type correctly for display.  Postgres 7.0 had no 'format_type'
16
     * built-in function, and hence we need to do it manually.
17
     *
18
     * @param string $typname The name of the type
19
     * @param int    $typmod  The contents of the typmod field
20
     *
21
     * @return bool|string
22
     */
23
    public function formatType($typname, $typmod)
24
    {
25
        // This is a specific constant in the 7.0 source
26
        $varhdrsz = 4;
27
28
        // If the first character is an underscore, it's an array type
29
        $is_array = false;
30
31
        if ('_' === \mb_substr($typname, 0, 1)) {
32
            $is_array = true;
33
            $typname = \mb_substr($typname, 1);
34
        }
35
36
        // Show lengths on bpchar and varchar
37
        if ('bpchar' === $typname) {
38
            $len = $typmod - $varhdrsz;
39
            $temp = 'character';
40
41
            if (1 < $len) {
42
                $temp .= "({$len})";
43
            }
44
        } elseif ('varchar' === $typname) {
45
            $temp = 'character varying';
46
47
            if (-1 !== $typmod) {
48
                $temp .= '(' . ($typmod - $varhdrsz) . ')';
49
            }
50
        } elseif ('numeric' === $typname) {
51
            $temp = 'numeric';
52
53
            if (-1 !== $typmod) {
54
                $tmp_typmod = $typmod - $varhdrsz;
55
                $precision = ($tmp_typmod >> 16) & 0xffff;
56
                $scale = $tmp_typmod & 0xffff;
57
                $temp .= "({$precision}, {$scale})";
58
            }
59
        } else {
60
            $temp = $typname;
61
        }
62
63
        // Add array qualifier if it's an array
64
        if ($is_array) {
65
            $temp .= '[]';
66
        }
67
68
        return $temp;
69
    }
70
71
    /**
72
     * Returns all details for a particular type.
73
     *
74
     * @param string $typname The name of the view to retrieve
75
     *
76
     * @return \ADORecordSet|int
77
     */
78
    public function getType($typname)
79
    {
80
        $this->clean($typname);
81
82
        $sql = "SELECT typtype, typbyval, typname, typinput AS typin, typoutput AS typout, typlen, typalign
83
            FROM pg_type WHERE typname='{$typname}'";
84
85
        return $this->selectSet($sql);
86
    }
87
88
    /**
89
     * Returns a list of all types in the database.
90
     *
91
     * @param bool $all        If true, will find all available types, if false just those in search path
92
     * @param bool $tabletypes If true, will include table types
93
     * @param bool $domains    If true, will include domains
94
     *
95
     * @return \ADORecordSet|int
96
     */
97
    public function getTypes($all = false, $tabletypes = false, $domains = false)
98
    {
99
        if ($all) {
100
            $where = '1 = 1';
101
        } else {
102
            $c_schema = $this->_schema;
103
            $this->clean($c_schema);
104
            $where = "n.nspname = '{$c_schema}'";
105
        }
106
        // Never show system table types
107
        $where2 = "AND c.relnamespace NOT IN (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname LIKE 'pg@_%' ESCAPE '@')";
108
109
        // Create type filter
110
        $tqry = "'c'";
111
112
        if ($tabletypes) {
113
            $tqry .= ", 'r', 'v'";
114
        }
115
116
        // Create domain filter
117
        if (!$domains) {
118
            $where .= " AND t.typtype != 'd'";
119
        }
120
121
        $sql = "SELECT
122
                t.typname AS basename,
123
                pg_catalog.format_type(t.oid, NULL) AS typname,
124
                pu.usename AS typowner,
125
                t.typtype,
126
                pg_catalog.obj_description(t.oid, 'pg_type') AS typcomment
127
            FROM (pg_catalog.pg_type t
128
                LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace)
129
                LEFT JOIN pg_catalog.pg_user pu ON t.typowner = pu.usesysid
130
            WHERE (t.typrelid = 0 OR (SELECT c.relkind IN ({$tqry}) FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid {$where2}))
131
            AND t.typname !~ '^_'
132
            AND {$where}
133
            ORDER BY typname
134
        ";
135
136
        return $this->selectSet($sql);
137
    }
138
139
    /**
140
     * Creates a new type.
141
     *
142
     * @param string $typname
143
     * @param string $typin
144
     * @param string $typout
145
     * @param string $typlen
146
     * @param string $typdef
147
     * @param string $typelem
148
     * @param string $typdelim
149
     * @param string $typbyval
150
     * @param string $typalign
151
     * @param string $typstorage
152
     *
153
     * @return \ADORecordSet|int
154
     *
155
     * @internal param $ ...
156
     */
157
    public function createType(
158
        $typname,
159
        $typin,
160
        $typout,
161
        $typlen,
162
        $typdef,
163
        $typelem,
164
        $typdelim,
165
        $typbyval,
166
        $typalign,
167
        $typstorage
168
    ) {
169
        $f_schema = $this->_schema;
170
        $this->fieldClean($f_schema);
171
        $this->fieldClean($typname);
172
        $this->fieldClean($typin);
173
        $this->fieldClean($typout);
174
175
        $sql = "
176
            CREATE TYPE \"{$f_schema}\".\"{$typname}\" (
177
                INPUT = \"{$typin}\",
178
                OUTPUT = \"{$typout}\",
179
                INTERNALLENGTH = {$typlen}";
180
181
        if ('' !== $typdef) {
182
            $sql .= ", DEFAULT = {$typdef}";
183
        }
184
185
        if ('' !== $typelem) {
186
            $sql .= ", ELEMENT = {$typelem}";
187
        }
188
189
        if ('' !== $typdelim) {
190
            $sql .= ", DELIMITER = {$typdelim}";
191
        }
192
193
        if ($typbyval) {
194
            $sql .= ', PASSEDBYVALUE, ';
195
        }
196
197
        if ('' !== $typalign) {
198
            $sql .= ", ALIGNMENT = {$typalign}";
199
        }
200
201
        if ('' !== $typstorage) {
202
            $sql .= ", STORAGE = {$typstorage}";
203
        }
204
205
        $sql .= ')';
206
207
        return $this->execute($sql);
208
    }
209
210
    /**
211
     * Drops a type.
212
     *
213
     * @param string $typname The name of the type to drop
214
     * @param bool   $cascade True to cascade drop, false to restrict
215
     *
216
     * @return \ADORecordSet|int
217
     */
218
    public function dropType($typname, $cascade)
219
    {
220
        $f_schema = $this->_schema;
221
        $this->fieldClean($f_schema);
222
        $this->fieldClean($typname);
223
224
        $sql = "DROP TYPE \"{$f_schema}\".\"{$typname}\"";
225
226
        if ($cascade) {
227
            $sql .= ' CASCADE';
228
        }
229
230
        return $this->execute($sql);
231
    }
232
233
    /**
234
     * Creates a new enum type in the database.
235
     *
236
     * @param string $name       The name of the type
237
     * @param array  $values     An array of values
238
     * @param string $typcomment Type comment
239
     *
240
     * @return bool|int 0 success
241
     */
242
    public function createEnumType($name, $values, $typcomment)
243
    {
244
        $f_schema = $this->_schema;
245
        $this->fieldClean($f_schema);
246
        $this->fieldClean($name);
247
248
        if (empty($values)) {
249
            return -2;
250
        }
251
252
        $status = $this->beginTransaction();
253
254
        if (0 !== $status) {
255
            return -1;
256
        }
257
258
        $values = \array_unique($values);
259
260
        $nbval = \count($values);
261
262
        for ($i = 0; $i < $nbval; ++$i) {
263
            $this->clean($values[$i]);
264
        }
265
266
        $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS ENUM ('";
267
        $sql .= \implode("','", $values);
268
        $sql .= "')";
269
270
        $status = $this->execute($sql);
271
272
        if ($status) {
273
            $this->rollbackTransaction();
274
275
            return -1;
276
        }
277
278
        if ('' !== $typcomment) {
279
            $status = $this->setComment('TYPE', $name, '', $typcomment, true);
280
281
            if ($status) {
282
                $this->rollbackTransaction();
283
284
                return -1;
285
            }
286
        }
287
288
        return $this->endTransaction();
289
    }
290
291
    /**
292
     * Get defined values for a given enum.
293
     *
294
     * @param string $name
295
     *
296
     * @return \ADORecordSet|int
297
     */
298
    public function getEnumValues($name)
299
    {
300
        $this->clean($name);
301
302
        $sql = "SELECT enumlabel AS enumval
303
        FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON (t.oid=e.enumtypid)
304
        WHERE t.typname = '{$name}' ORDER BY e.oid";
305
306
        return $this->selectSet($sql);
307
    }
308
309
    // Operator functions
310
311
    /**
312
     * Creates a new composite type in the database.
313
     *
314
     * @param string $name       The name of the type
315
     * @param int    $fields     The number of fields
316
     * @param array  $field      An array of field names
317
     * @param array  $type       An array of field types
318
     * @param array  $array      An array of '' or '[]' for each type if it's an array or not
319
     * @param array  $length     An array of field lengths
320
     * @param array  $colcomment An array of comments
321
     * @param string $typcomment Type comment
322
     *
323
     * @return bool|int 0 success
324
     */
325
    public function createCompositeType($name, $fields, $field, $type, $array, $length, $colcomment, $typcomment)
326
    {
327
        $f_schema = $this->_schema;
328
        $this->fieldClean($f_schema);
329
        $this->fieldClean($name);
330
331
        $status = $this->beginTransaction();
332
333
        if (0 !== $status) {
334
            return -1;
335
        }
336
337
        $found = false;
338
        $first = true;
339
        $comment_sql = ''; // Accumulate comments for the columns
340
        $sql = "CREATE TYPE \"{$f_schema}\".\"{$name}\" AS (";
341
342
        for ($i = 0; $i < $fields; ++$i) {
343
            $this->fieldClean($field[$i]);
344
            $this->clean($type[$i]);
345
            $this->clean($length[$i]);
346
            $this->clean($colcomment[$i]);
347
348
            // Skip blank columns - for user convenience
349
            if ('' === $field[$i] || '' === $type[$i]) {
350
                continue;
351
            }
352
353
            // If not the first column, add a comma
354
            if (!$first) {
355
                $sql .= ', ';
356
            } else {
357
                $first = false;
358
            }
359
360
            switch ($type[$i]) {
361
                // Have to account for weird placing of length for with/without
362
                // time zone types
363
                case 'timestamp with time zone':
364
                case 'timestamp without time zone':
365
                    $qual = \mb_substr($type[$i], 9);
366
                    $sql .= "\"{$field[$i]}\" timestamp";
367
368
                    if ('' !== $length[$i]) {
369
                        $sql .= "({$length[$i]})";
370
                    }
371
372
                    $sql .= $qual;
373
374
                    break;
375
                case 'time with time zone':
376
                case 'time without time zone':
377
                    $qual = \mb_substr($type[$i], 4);
378
                    $sql .= "\"{$field[$i]}\" time";
379
380
                    if ('' !== $length[$i]) {
381
                        $sql .= "({$length[$i]})";
382
                    }
383
384
                    $sql .= $qual;
385
386
                    break;
387
388
                default:
389
                    $sql .= "\"{$field[$i]}\" {$type[$i]}";
390
391
                    if ('' !== $length[$i]) {
392
                        $sql .= "({$length[$i]})";
393
                    }
394
            }
395
            // Add array qualifier if necessary
396
            if ('[]' === $array[$i]) {
397
                $sql .= '[]';
398
            }
399
400
            if ('' !== $colcomment[$i]) {
401
                $comment_sql .= "COMMENT ON COLUMN \"{$f_schema}\".\"{$name}\".\"{$field[$i]}\" IS '{$colcomment[$i]}';\n";
402
            }
403
404
            $found = true;
405
        }
406
407
        if (!$found) {
0 ignored issues
show
introduced by
The condition $found is always false.
Loading history...
408
            return -1;
409
        }
410
411
        $sql .= ')';
412
413
        $status = $this->execute($sql);
414
415
        if ($status) {
416
            $this->rollbackTransaction();
417
418
            return -1;
419
        }
420
421
        if ('' !== $typcomment) {
422
            $status = $this->setComment('TYPE', $name, '', $typcomment, true);
423
424
            if ($status) {
425
                $this->rollbackTransaction();
426
427
                return -1;
428
            }
429
        }
430
431
        if ('' !== $comment_sql) {
432
            $status = $this->execute($comment_sql);
433
434
            if ($status) {
435
                $this->rollbackTransaction();
436
437
                return -1;
438
            }
439
        }
440
441
        return $this->endTransaction();
442
    }
443
444
    /**
445
     * Returns a list of all casts in the database.
446
     *
447
     * @return \ADORecordSet|int
448
     */
449
    public function getCasts()
450
    {
451
        $conf = $this->conf;
452
453
        if ($conf['show_system']) {
454
            $where = '';
455
        } else {
456
            $where = '
457
                AND n1.nspname NOT LIKE $$pg\_%$$
458
                AND n2.nspname NOT LIKE $$pg\_%$$
459
                AND n3.nspname NOT LIKE $$pg\_%$$
460
            ';
461
        }
462
463
        $sql = "
464
            SELECT
465
                c.castsource::pg_catalog.regtype AS castsource,
466
                c.casttarget::pg_catalog.regtype AS casttarget,
467
                CASE WHEN c.castfunc=0 THEN NULL
468
                ELSE c.castfunc::pg_catalog.regprocedure END AS castfunc,
469
                c.castcontext,
470
                obj_description(c.oid, 'pg_cast') as castcomment
471
            FROM
472
                (pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p ON c.castfunc=p.oid JOIN pg_catalog.pg_namespace n3 ON p.pronamespace=n3.oid),
473
                pg_catalog.pg_type t1,
474
                pg_catalog.pg_type t2,
475
                pg_catalog.pg_namespace n1,
476
                pg_catalog.pg_namespace n2
477
            WHERE
478
                c.castsource=t1.oid
479
                AND c.casttarget=t2.oid
480
                AND t1.typnamespace=n1.oid
481
                AND t2.typnamespace=n2.oid
482
                {$where}
483
            ORDER BY 1, 2
484
        ";
485
486
        return $this->selectSet($sql);
487
    }
488
489
    /**
490
     * Returns a list of all conversions in the database.
491
     *
492
     * @return \ADORecordSet|int
493
     */
494
    public function getConversions()
495
    {
496
        $c_schema = $this->_schema;
497
        $this->clean($c_schema);
498
        $sql = "
499
            SELECT
500
                   c.conname,
501
                   pg_catalog.pg_encoding_to_char(c.conforencoding) AS conforencoding,
502
                   pg_catalog.pg_encoding_to_char(c.contoencoding) AS contoencoding,
503
                   c.condefault,
504
                   pg_catalog.obj_description(c.oid, 'pg_conversion') AS concomment
505
            FROM pg_catalog.pg_conversion c, pg_catalog.pg_namespace n
506
            WHERE n.oid = c.connamespace
507
                  AND n.nspname='{$c_schema}'
508
            ORDER BY 1;
509
        ";
510
511
        return $this->selectSet($sql);
512
    }
513
514
    abstract public function fieldClean(&$str);
515
516
    abstract public function beginTransaction();
517
518
    abstract public function rollbackTransaction();
519
520
    abstract public function endTransaction();
521
522
    abstract public function execute($sql);
523
524
    abstract public function setComment($obj_type, $obj_name, $table, $comment, $basetype = null);
525
526
    abstract public function selectSet($sql);
527
528
    abstract public function clean(&$str);
529
530
    abstract public function phpBool($parameter);
531
532
    abstract public function hasCreateTableLikeWithConstraints();
533
534
    abstract public function hasCreateTableLikeWithIndexes();
535
536
    abstract public function hasTablespaces();
537
538
    abstract public function delete($table, $conditions, $schema = '');
539
540
    abstract public function fieldArrayClean(&$arr);
541
542
    abstract public function hasCreateFieldWithConstraints();
543
544
    abstract public function getAttributeNames($table, $atts);
545
}
546