Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like PostgreSqlPlatform 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 PostgreSqlPlatform, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
43 | class PostgreSqlPlatform extends AbstractPlatform |
||
44 | { |
||
45 | /** |
||
46 | * @var bool |
||
47 | */ |
||
48 | private $useBooleanTrueFalseStrings = true; |
||
49 | |||
50 | /** |
||
51 | * @var array PostgreSQL booleans literals |
||
52 | */ |
||
53 | private $booleanLiterals = array( |
||
54 | 'true' => array( |
||
55 | 't', |
||
56 | 'true', |
||
57 | 'y', |
||
58 | 'yes', |
||
59 | 'on', |
||
60 | '1' |
||
61 | ), |
||
62 | 'false' => array( |
||
63 | 'f', |
||
64 | 'false', |
||
65 | 'n', |
||
66 | 'no', |
||
67 | 'off', |
||
68 | '0' |
||
69 | ) |
||
70 | ); |
||
71 | |||
72 | /** |
||
73 | * PostgreSQL has different behavior with some drivers |
||
74 | * with regard to how booleans have to be handled. |
||
75 | * |
||
76 | * Enables use of 'true'/'false' or otherwise 1 and 0 instead. |
||
77 | * |
||
78 | * @param bool $flag |
||
79 | */ |
||
80 | 8 | public function setUseBooleanTrueFalseStrings($flag) |
|
84 | |||
85 | /** |
||
86 | * {@inheritDoc} |
||
87 | */ |
||
88 | 4 | View Code Duplication | public function getSubstringExpression($value, $from, $length = null) |
96 | |||
97 | /** |
||
98 | * {@inheritDoc} |
||
99 | */ |
||
100 | public function getNowExpression() |
||
104 | |||
105 | /** |
||
106 | * {@inheritDoc} |
||
107 | */ |
||
108 | 4 | public function getRegexpExpression() |
|
112 | |||
113 | /** |
||
114 | * {@inheritDoc} |
||
115 | */ |
||
116 | public function getLocateExpression($str, $substr, $startPos = false) |
||
126 | |||
127 | /** |
||
128 | * {@inheritdoc} |
||
129 | */ |
||
130 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
||
139 | |||
140 | /** |
||
141 | * {@inheritDoc} |
||
142 | */ |
||
143 | public function getDateDiffExpression($date1, $date2) |
||
147 | |||
148 | /** |
||
149 | * {@inheritDoc} |
||
150 | */ |
||
151 | 4 | public function supportsSequences() |
|
155 | |||
156 | /** |
||
157 | * {@inheritDoc} |
||
158 | */ |
||
159 | public function supportsSchemas() |
||
163 | |||
164 | /** |
||
165 | * {@inheritdoc} |
||
166 | */ |
||
167 | public function getDefaultSchemaName() |
||
171 | |||
172 | /** |
||
173 | * {@inheritDoc} |
||
174 | */ |
||
175 | 4 | public function supportsIdentityColumns() |
|
179 | |||
180 | /** |
||
181 | * {@inheritdoc} |
||
182 | */ |
||
183 | 34 | public function supportsPartialIndexes() |
|
187 | |||
188 | /** |
||
189 | * {@inheritdoc} |
||
190 | */ |
||
191 | 4 | public function usesSequenceEmulatedIdentityColumns() |
|
195 | |||
196 | /** |
||
197 | * {@inheritdoc} |
||
198 | */ |
||
199 | 4 | public function getIdentitySequenceName($tableName, $columnName) |
|
203 | |||
204 | /** |
||
205 | * {@inheritDoc} |
||
206 | */ |
||
207 | 60 | public function supportsCommentOnStatement() |
|
211 | |||
212 | /** |
||
213 | * {@inheritDoc} |
||
214 | */ |
||
215 | 4 | public function prefersSequences() |
|
219 | |||
220 | /** |
||
221 | * {@inheritDoc} |
||
222 | */ |
||
223 | 196 | public function hasNativeGuidType() |
|
227 | |||
228 | /** |
||
229 | * {@inheritDoc} |
||
230 | */ |
||
231 | public function getListDatabasesSQL() |
||
235 | |||
236 | /** |
||
237 | * {@inheritDoc} |
||
238 | */ |
||
239 | public function getListNamespacesSQL() |
||
246 | |||
247 | /** |
||
248 | * {@inheritDoc} |
||
249 | */ |
||
250 | public function getListSequencesSQL($database) |
||
258 | |||
259 | /** |
||
260 | * {@inheritDoc} |
||
261 | */ |
||
262 | public function getListTablesSQL() |
||
273 | |||
274 | /** |
||
275 | * {@inheritDoc} |
||
276 | */ |
||
277 | public function getListViewsSQL($database) |
||
285 | |||
286 | /** |
||
287 | * {@inheritDoc} |
||
288 | */ |
||
289 | 8 | public function getListTableForeignKeysSQL($table, $database = null) |
|
301 | |||
302 | /** |
||
303 | * {@inheritDoc} |
||
304 | */ |
||
305 | public function getCreateViewSQL($name, $sql) |
||
309 | |||
310 | /** |
||
311 | * {@inheritDoc} |
||
312 | */ |
||
313 | public function getDropViewSQL($name) |
||
317 | |||
318 | /** |
||
319 | * {@inheritDoc} |
||
320 | */ |
||
321 | 4 | public function getListTableConstraintsSQL($table) |
|
338 | |||
339 | /** |
||
340 | * {@inheritDoc} |
||
341 | * |
||
342 | * @license New BSD License |
||
343 | * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html |
||
344 | */ |
||
345 | 8 | public function getListTableIndexesSQL($table, $currentDatabase = null) |
|
357 | |||
358 | /** |
||
359 | * @param string $table |
||
360 | * @param string $classAlias |
||
361 | * @param string $namespaceAlias |
||
362 | * |
||
363 | * @return string |
||
364 | */ |
||
365 | 24 | private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n') |
|
381 | |||
382 | /** |
||
383 | * {@inheritDoc} |
||
384 | */ |
||
385 | 8 | public function getListTableColumnsSQL($table, $database = null) |
|
418 | |||
419 | /** |
||
420 | * {@inheritDoc} |
||
421 | */ |
||
422 | 4 | public function getCreateDatabaseSQL($name) |
|
426 | |||
427 | /** |
||
428 | * Returns the SQL statement for disallowing new connections on the given database. |
||
429 | * |
||
430 | * This is useful to force DROP DATABASE operations which could fail because of active connections. |
||
431 | * |
||
432 | * @param string $database The name of the database to disallow new connections for. |
||
433 | * |
||
434 | * @return string |
||
435 | */ |
||
436 | 4 | public function getDisallowDatabaseConnectionsSQL($database) |
|
440 | |||
441 | /** |
||
442 | * Returns the SQL statement for closing currently active connections on the given database. |
||
443 | * |
||
444 | * This is useful to force DROP DATABASE operations which could fail because of active connections. |
||
445 | * |
||
446 | * @param string $database The name of the database to close currently active connections for. |
||
447 | * |
||
448 | * @return string |
||
449 | */ |
||
450 | 4 | public function getCloseActiveDatabaseConnectionsSQL($database) |
|
456 | |||
457 | /** |
||
458 | * {@inheritDoc} |
||
459 | */ |
||
460 | 20 | public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey) |
|
486 | |||
487 | /** |
||
488 | * {@inheritDoc} |
||
489 | */ |
||
490 | 72 | public function getAlterTableSQL(TableDiff $diff) |
|
624 | |||
625 | /** |
||
626 | * Checks whether a given column diff is a logically unchanged binary type column. |
||
627 | * |
||
628 | * Used to determine whether a column alteration for a binary type column can be skipped. |
||
629 | * Doctrine's {@link \Doctrine\DBAL\Types\BinaryType} and {@link \Doctrine\DBAL\Types\BlobType} |
||
630 | * are mapped to the same database column type on this platform as this platform |
||
631 | * does not have a native VARBINARY/BINARY column type. Therefore the {@link \Doctrine\DBAL\Schema\Comparator} |
||
632 | * might detect differences for binary type columns which do not have to be propagated |
||
633 | * to database as there actually is no difference at database level. |
||
634 | * |
||
635 | * @param ColumnDiff $columnDiff The column diff to check against. |
||
636 | * |
||
637 | * @return boolean True if the given column diff is an unchanged binary type column, false otherwise. |
||
638 | */ |
||
639 | 40 | private function isUnchangedBinaryColumn(ColumnDiff $columnDiff) |
|
665 | |||
666 | /** |
||
667 | * {@inheritdoc} |
||
668 | */ |
||
669 | 20 | View Code Duplication | protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) |
678 | |||
679 | /** |
||
680 | * {@inheritdoc} |
||
681 | */ |
||
682 | 28 | View Code Duplication | public function getCommentOnColumnSQL($tableName, $columnName, $comment) |
691 | |||
692 | /** |
||
693 | * {@inheritDoc} |
||
694 | */ |
||
695 | 8 | View Code Duplication | public function getCreateSequenceSQL(Sequence $sequence) |
703 | |||
704 | /** |
||
705 | * {@inheritDoc} |
||
706 | */ |
||
707 | public function getAlterSequenceSQL(Sequence $sequence) |
||
713 | |||
714 | /** |
||
715 | * Cache definition for sequences |
||
716 | * |
||
717 | * @param Sequence $sequence |
||
718 | * |
||
719 | * @return string |
||
720 | */ |
||
721 | 8 | private function getSequenceCacheSQL(Sequence $sequence) |
|
729 | |||
730 | /** |
||
731 | * {@inheritDoc} |
||
732 | */ |
||
733 | 4 | public function getDropSequenceSQL($sequence) |
|
741 | |||
742 | /** |
||
743 | * {@inheritDoc} |
||
744 | */ |
||
745 | 4 | public function getCreateSchemaSQL($schemaName) |
|
749 | |||
750 | /** |
||
751 | * {@inheritDoc} |
||
752 | */ |
||
753 | 12 | public function getDropForeignKeySQL($foreignKey, $table) |
|
757 | |||
758 | /** |
||
759 | * {@inheritDoc} |
||
760 | */ |
||
761 | 56 | protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) |
|
788 | |||
789 | /** |
||
790 | * Converts a single boolean value. |
||
791 | * |
||
792 | * First converts the value to its native PHP boolean type |
||
793 | * and passes it to the given callback function to be reconverted |
||
794 | * into any custom representation. |
||
795 | * |
||
796 | * @param mixed $value The value to convert. |
||
797 | * @param callable $callback The callback function to use for converting the real boolean value. |
||
798 | * |
||
799 | * @return mixed |
||
800 | * @throws \UnexpectedValueException |
||
801 | */ |
||
802 | 128 | private function convertSingleBooleanValue($value, $callback) |
|
829 | |||
830 | /** |
||
831 | * Converts one or multiple boolean values. |
||
832 | * |
||
833 | * First converts the value(s) to their native PHP boolean type |
||
834 | * and passes them to the given callback function to be reconverted |
||
835 | * into any custom representation. |
||
836 | * |
||
837 | * @param mixed $item The value(s) to convert. |
||
838 | * @param callable $callback The callback function to use for converting the real boolean value(s). |
||
839 | * |
||
840 | * @return mixed |
||
841 | */ |
||
842 | private function doConvertBooleans($item, $callback) |
||
854 | |||
855 | /** |
||
856 | * {@inheritDoc} |
||
857 | * |
||
858 | * Postgres wants boolean values converted to the strings 'true'/'false'. |
||
859 | */ |
||
860 | public function convertBooleans($item) |
||
877 | |||
878 | /** |
||
879 | * {@inheritDoc} |
||
880 | */ |
||
881 | public function convertBooleansToDatabaseValue($item) |
||
894 | |||
895 | /** |
||
896 | * {@inheritDoc} |
||
897 | */ |
||
898 | public function convertFromBoolean($item) |
||
906 | |||
907 | /** |
||
908 | * {@inheritDoc} |
||
909 | */ |
||
910 | public function getSequenceNextValSQL($sequenceName) |
||
914 | |||
915 | /** |
||
916 | * {@inheritDoc} |
||
917 | */ |
||
918 | public function getSetTransactionIsolationSQL($level) |
||
923 | |||
924 | /** |
||
925 | * {@inheritDoc} |
||
926 | */ |
||
927 | public function getBooleanTypeDeclarationSQL(array $field) |
||
931 | |||
932 | /** |
||
933 | * {@inheritDoc} |
||
934 | */ |
||
935 | public function getIntegerTypeDeclarationSQL(array $field) |
||
943 | |||
944 | /** |
||
945 | * {@inheritDoc} |
||
946 | */ |
||
947 | public function getBigIntTypeDeclarationSQL(array $field) |
||
955 | |||
956 | /** |
||
957 | * {@inheritDoc} |
||
958 | */ |
||
959 | public function getSmallIntTypeDeclarationSQL(array $field) |
||
963 | |||
964 | /** |
||
965 | * {@inheritDoc} |
||
966 | */ |
||
967 | public function getGuidTypeDeclarationSQL(array $field) |
||
971 | |||
972 | /** |
||
973 | * {@inheritDoc} |
||
974 | */ |
||
975 | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
979 | |||
980 | /** |
||
981 | * {@inheritDoc} |
||
982 | */ |
||
983 | public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) |
||
987 | |||
988 | /** |
||
989 | * {@inheritDoc} |
||
990 | */ |
||
991 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
||
995 | |||
996 | /** |
||
997 | * {@inheritDoc} |
||
998 | */ |
||
999 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
1003 | |||
1004 | /** |
||
1005 | * {@inheritDoc} |
||
1006 | */ |
||
1007 | public function getGuidExpression() |
||
1011 | |||
1012 | /** |
||
1013 | * {@inheritDoc} |
||
1014 | */ |
||
1015 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
||
1019 | |||
1020 | /** |
||
1021 | * {@inheritDoc} |
||
1022 | */ |
||
1023 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
||
1028 | |||
1029 | /** |
||
1030 | * {@inheritdoc} |
||
1031 | */ |
||
1032 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
||
1036 | |||
1037 | /** |
||
1038 | * {@inheritDoc} |
||
1039 | */ |
||
1040 | public function getClobTypeDeclarationSQL(array $field) |
||
1044 | |||
1045 | /** |
||
1046 | * {@inheritDoc} |
||
1047 | */ |
||
1048 | public function getName() |
||
1052 | |||
1053 | /** |
||
1054 | * {@inheritDoc} |
||
1055 | * |
||
1056 | * PostgreSQL returns all column names in SQL result sets in lowercase. |
||
1057 | */ |
||
1058 | public function getSQLResultCasing($column) |
||
1062 | |||
1063 | /** |
||
1064 | * {@inheritDoc} |
||
1065 | */ |
||
1066 | public function getDateTimeTzFormatString() |
||
1070 | |||
1071 | /** |
||
1072 | * {@inheritDoc} |
||
1073 | */ |
||
1074 | public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) |
||
1078 | |||
1079 | /** |
||
1080 | * {@inheritDoc} |
||
1081 | */ |
||
1082 | public function getTruncateTableSQL($tableName, $cascade = false) |
||
1093 | |||
1094 | /** |
||
1095 | * {@inheritDoc} |
||
1096 | */ |
||
1097 | public function getReadLockSQL() |
||
1101 | |||
1102 | /** |
||
1103 | * {@inheritDoc} |
||
1104 | */ |
||
1105 | View Code Duplication | protected function initializeDoctrineTypeMappings() |
|
1149 | |||
1150 | /** |
||
1151 | * {@inheritDoc} |
||
1152 | */ |
||
1153 | public function getVarcharMaxLength() |
||
1157 | |||
1158 | /** |
||
1159 | * {@inheritdoc} |
||
1160 | */ |
||
1161 | public function getBinaryMaxLength() |
||
1165 | |||
1166 | /** |
||
1167 | * {@inheritdoc} |
||
1168 | */ |
||
1169 | public function getBinaryDefaultLength() |
||
1173 | |||
1174 | /** |
||
1175 | * {@inheritDoc} |
||
1176 | */ |
||
1177 | protected function getReservedKeywordsClass() |
||
1181 | |||
1182 | /** |
||
1183 | * {@inheritDoc} |
||
1184 | */ |
||
1185 | public function getBlobTypeDeclarationSQL(array $field) |
||
1189 | |||
1190 | /** |
||
1191 | * {@inheritdoc} |
||
1192 | */ |
||
1193 | public function quoteStringLiteral($str) |
||
1199 | |||
1200 | /** |
||
1201 | * {@inheritdoc} |
||
1202 | */ |
||
1203 | public function getDefaultValueDeclarationSQL($field) |
||
1211 | |||
1212 | private function isSerialField(array $field) : bool |
||
1217 | |||
1218 | /** |
||
1219 | * Check whether the type of a column is changed in a way that invalidates the default value for the column |
||
1220 | * |
||
1221 | * @param ColumnDiff $columnDiff |
||
1222 | * @return bool |
||
1223 | */ |
||
1224 | private function typeChangeBreaksDefaultValue(ColumnDiff $columnDiff) : bool |
||
1237 | |||
1238 | private function isNumericType(Type $type) : bool |
||
1242 | } |
||
1243 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.