Total Complexity | 55 |
Total Lines | 533 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like TypeTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use TypeTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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) |
||
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) |
||
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) { |
||
|
|||
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() |
||
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 |