| Total Complexity | 52 |
| Total Lines | 338 |
| Duplicated Lines | 0 % |
| Changes | 11 | ||
| Bugs | 0 | Features | 0 |
Complex classes like Postgresql 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 Postgresql, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 7 | class Postgresql extends AbstractDatabaseManipulator |
||
| 8 | { |
||
| 9 | |||
| 10 | private function buildTableName($name, $schema) |
||
| 11 | { |
||
| 12 | return ($schema === false || $schema == '' ? '' : "\"{$schema}\".") . "\"$name\""; |
||
| 13 | } |
||
| 14 | |||
| 15 | private function setSearchField($details) |
||
| 16 | { |
||
| 17 | if ($details['schema'] != null) { |
||
| 18 | $this->query( |
||
| 19 | sprintf('SET search_path TO "%s", public', $details['schema']) |
||
| 20 | ); |
||
| 21 | } |
||
| 22 | } |
||
| 23 | |||
| 24 | protected function getDriverName() |
||
| 25 | { |
||
| 26 | return 'pgsql'; |
||
| 27 | } |
||
| 28 | |||
| 29 | #[\Override] |
||
| 30 | protected function _addSchema($name) |
||
| 31 | { |
||
| 32 | $this->query(sprintf('CREATE SCHEMA "%s"', $name)); |
||
| 33 | } |
||
| 34 | |||
| 35 | #[\Override] |
||
| 36 | protected function _dropSchema($name) |
||
| 37 | { |
||
| 38 | $this->query(sprintf('DROP SCHEMA "%s"', $name)); |
||
| 39 | } |
||
| 40 | |||
| 41 | #[\Override] |
||
| 42 | protected function _addTable($details) |
||
| 43 | { |
||
| 44 | $this->query(sprintf('CREATE TABLE %s ()', $this->buildTableName($details['name'], $details['schema']))); |
||
| 45 | } |
||
| 46 | |||
| 47 | #[\Override] |
||
| 48 | protected function _addView($details) |
||
| 49 | { |
||
| 50 | $this->setSearchField($details); |
||
| 51 | $this->query(sprintf('CREATE VIEW %s AS %s', $this->buildTableName($details['name'], $details['schema']), $details['definition'])); |
||
| 52 | } |
||
| 53 | |||
| 54 | #[\Override] |
||
| 55 | protected function _dropView($details) |
||
| 56 | { |
||
| 57 | $this->query(sprintf('DROP VIEW %s', $this->buildTableName($details['name'], $details['schema']))); |
||
| 58 | } |
||
| 59 | |||
| 60 | #[\Override] |
||
| 61 | protected function _changeViewDefinition($details) |
||
| 62 | { |
||
| 63 | $this->setSearchField($details['to']); |
||
| 64 | $name = $this->buildTableName($details['to']['name'], $details['to']['schema']); |
||
| 65 | $this->query(sprintf("CREATE OR REPLACE VIEW %s AS %s", $name, $details['to']['definition'])); |
||
| 66 | } |
||
| 67 | |||
| 68 | #[\Override] |
||
| 69 | protected function _dropTable($details) |
||
| 70 | { |
||
| 71 | $primaryKey = $this->query( |
||
| 72 | "select column_default from |
||
| 73 | information_schema.table_constraints pk |
||
| 74 | join information_schema.key_column_usage c on |
||
| 75 | c.table_name = pk.table_name and |
||
| 76 | c.constraint_name = pk.constraint_name and |
||
| 77 | c.constraint_schema = pk.table_schema |
||
| 78 | join information_schema.columns cl on |
||
| 79 | cl.table_name = c.table_name and |
||
| 80 | cl.table_schema = pk.table_schema and |
||
| 81 | cl.column_name = c.column_name |
||
| 82 | |||
| 83 | where pk.table_name = ? and pk.table_schema=? |
||
| 84 | and constraint_type = 'PRIMARY KEY'", array($details['name'], $details['schema'] == '' ? $this->getDefaultSchema() : $details['schema']) |
||
| 85 | ); |
||
| 86 | $this->query(sprintf('DROP TABLE %s', $this->buildTableName($details['name'], $details['schema']))); |
||
| 87 | |||
| 88 | if ($primaryKey) { |
||
| 89 | if (preg_match("/nextval\(\'(?<sequence>.*)\'\:\:regclass\)/i", $primaryKey[0]['column_default'] ?? '', $matches)) { |
||
| 90 | $this->query(sprintf('DROP SEQUENCE IF EXISTS "%s"', $matches['sequence'])); |
||
| 91 | } |
||
| 92 | } |
||
| 93 | } |
||
| 94 | |||
| 95 | public function describe() |
||
| 96 | { |
||
| 97 | $descriptor = new \yentu\descriptors\Postgresql($this); |
||
|
|
|||
| 98 | return $descriptor->describe(); |
||
| 99 | } |
||
| 100 | |||
| 101 | #[\Override] |
||
| 102 | protected function _addColumn($details) |
||
| 103 | { |
||
| 104 | $this->query( |
||
| 105 | sprintf('ALTER TABLE %s ADD COlUMN "%s" %s', $this->buildTableName($details['table'], $details['schema']), $details['name'], $this->convertTypes( |
||
| 106 | $details['type'], self::CONVERT_TO_DRIVER, $details['length'] |
||
| 107 | ) |
||
| 108 | ) |
||
| 109 | ); |
||
| 110 | $this->_changeColumnNulls($details); |
||
| 111 | $this->_changeColumnDefault($details); |
||
| 112 | } |
||
| 113 | |||
| 114 | #[\Override] |
||
| 115 | protected function _dropColumn($details) |
||
| 116 | { |
||
| 117 | $this->query( |
||
| 118 | sprintf( |
||
| 119 | 'ALTER TABLE %s DROP COLUMN "%s"', $this->buildTableName($details['table'], $details['schema']), $details['name'] |
||
| 120 | ) |
||
| 121 | ); |
||
| 122 | } |
||
| 123 | |||
| 124 | #[\Override] |
||
| 125 | protected function _changeColumnDefault($details) |
||
| 126 | { |
||
| 127 | $details = Parameters::wrap($details, ['default']); |
||
| 128 | $query = 'ALTER TABLE %s ALTER COLUMN "%s" '; |
||
| 129 | if ($details['default'] != '') { |
||
| 130 | $tableName = $this->buildTableName($details['table'], $details['schema']); |
||
| 131 | $columnName = $details['name']; |
||
| 132 | $default = "SET DEFAULT {$details['default']}"; |
||
| 133 | $this->query(sprintf($query . $default, $tableName, $columnName)); |
||
| 134 | } else if (isset($details['to'])) { |
||
| 135 | if ($details['to']['default'] != '') { |
||
| 136 | $tableName = $this->buildTableName($details['to']['table'], $details['to']['schema']); |
||
| 137 | $columnName = $details['to']['name']; |
||
| 138 | $default = "SET DEFAULT {$details['to']['default']}"; |
||
| 139 | } else if ($details['to']['default'] == '' && $details['from']['default'] != '') { |
||
| 140 | $tableName = $this->buildTableName($details['to']['table'], $details['to']['schema']); |
||
| 141 | $columnName = $details['to']['name']; |
||
| 142 | $default = "DROP DEFAULT"; |
||
| 143 | } |
||
| 144 | $this->query(sprintf($query . $default, $tableName, $columnName)); |
||
| 145 | } |
||
| 146 | } |
||
| 147 | |||
| 148 | /** |
||
| 149 | * |
||
| 150 | * @param array $details |
||
| 151 | */ |
||
| 152 | #[\Override] |
||
| 153 | protected function _changeColumnNulls($details) |
||
| 154 | { |
||
| 155 | $details = Parameters::wrap($details, ['nulls']); |
||
| 156 | $query = 'ALTER TABLE %s ALTER COLUMN "%s" '; |
||
| 157 | |||
| 158 | if ($details['nulls'] === false) { |
||
| 159 | $tableName = $this->buildTableName($details['table'], $details['schema']); |
||
| 160 | $columnName = $details['name']; |
||
| 161 | $null = ' SET NOT NULL'; |
||
| 162 | $this->query(sprintf($query . $null, $tableName, $columnName)); |
||
| 163 | } else if (isset($details['to'])) { |
||
| 164 | if ($details['to']['nulls'] === false) { |
||
| 165 | $tableName = $this->buildTableName($details['to']['table'], $details['to']['schema']); |
||
| 166 | $columnName = $details['to']['name']; |
||
| 167 | $null = ' SET NOT NULL'; |
||
| 168 | } else { |
||
| 169 | $tableName = $this->buildTableName($details['to']['table'], $details['to']['schema']); |
||
| 170 | $columnName = $details['to']['name']; |
||
| 171 | $null = ' DROP NOT NULL'; |
||
| 172 | } |
||
| 173 | $this->query(sprintf($query . $null, $tableName, $columnName)); |
||
| 174 | } |
||
| 175 | } |
||
| 176 | |||
| 177 | #[\Override] |
||
| 178 | protected function _changeColumnName($details) |
||
| 179 | { |
||
| 180 | $this->query( |
||
| 181 | sprintf( |
||
| 182 | 'ALTER TABLE %s RENAME COLUMN "%s" TO "%s"', $this->buildTableName($details['to']['table'], $details['to']['schema']), $details['from']['name'], $details['to']['name'] |
||
| 183 | ) |
||
| 184 | ); |
||
| 185 | } |
||
| 186 | |||
| 187 | #[\Override] |
||
| 188 | protected function _addPrimaryKey($details) |
||
| 189 | { |
||
| 190 | $this->query( |
||
| 191 | sprintf( |
||
| 192 | 'ALTER TABLE %s ADD CONSTRAINT "%s" PRIMARY KEY ("%s")', $this->buildTableName($details['table'], $details['schema']), $details['name'], implode('","', $details['columns']) |
||
| 193 | ) |
||
| 194 | ); |
||
| 195 | } |
||
| 196 | |||
| 197 | #[\Override] |
||
| 198 | protected function _dropPrimaryKey($details) |
||
| 199 | { |
||
| 200 | $this->query( |
||
| 201 | sprintf( |
||
| 202 | 'ALTER TABLE %s DROP CONSTRAINT "%s" CASCADE', $this->buildTableName($details['table'], $details['schema']), $details['name'] |
||
| 203 | ) |
||
| 204 | ); |
||
| 205 | } |
||
| 206 | |||
| 207 | #[\Override] |
||
| 208 | protected function _addUniqueKey($details) |
||
| 209 | { |
||
| 210 | $this->query( |
||
| 211 | sprintf( |
||
| 212 | 'ALTER TABLE %s ADD CONSTRAINT "%s" UNIQUE ("%s")', $this->buildTableName($details['table'], $details['schema']), $details['name'], implode('","', $details['columns']) |
||
| 213 | ) |
||
| 214 | ); |
||
| 215 | } |
||
| 216 | |||
| 217 | private function dropKeyItem($details, $type) |
||
| 218 | { |
||
| 219 | $this->query( |
||
| 220 | sprintf( |
||
| 221 | 'ALTER TABLE %s DROP CONSTRAINT "%s" CASCADE', $this->buildTableName($details['table'], $details['schema']), $details['name'] |
||
| 222 | ) |
||
| 223 | ); |
||
| 224 | |||
| 225 | //$this->dropTableItem($details, $type); |
||
| 226 | } |
||
| 227 | |||
| 228 | #[\Override] |
||
| 229 | protected function _dropUniqueKey($details) |
||
| 230 | { |
||
| 231 | $this->dropKeyItem($details, 'unique_keys'); |
||
| 232 | } |
||
| 233 | |||
| 234 | #[\Override] |
||
| 235 | protected function _addAutoPrimaryKey($details) |
||
| 236 | { |
||
| 237 | $sequence = $this->buildTableName("{$details['table']}_{$details['column']}_seq", $details['schema']); |
||
| 238 | $this->query("CREATE SEQUENCE $sequence"); |
||
| 239 | $this->query( |
||
| 240 | sprintf( |
||
| 241 | 'ALTER TABLE %s ALTER COLUMN "%s" SET DEFAULT nextval(\'%s\')', $this->buildTableName($details['table'], |
||
| 242 | $details['schema']), $details['column'], $sequence |
||
| 243 | ) |
||
| 244 | ); |
||
| 245 | } |
||
| 246 | |||
| 247 | #[\Override] |
||
| 248 | protected function _dropAutoPrimaryKey($details) |
||
| 249 | { |
||
| 250 | $sequence = $this->buildTableName("{$details['table']}_{$details['column']}_seq", $details['schema']); |
||
| 251 | $this->query( |
||
| 252 | sprintf( |
||
| 253 | 'ALTER TABLE %s ALTER COLUMN "%s" SET DEFAULT NULL', $this->buildTableName($details['table'], |
||
| 254 | $details['schema']), $details['column'], $sequence |
||
| 255 | ) |
||
| 256 | ); |
||
| 257 | $this->query("DROP SEQUENCE IF EXISTS $sequence"); |
||
| 258 | } |
||
| 259 | |||
| 260 | #[\Override] |
||
| 261 | protected function _addForeignKey($details) |
||
| 262 | { |
||
| 263 | $this->query( |
||
| 264 | sprintf( |
||
| 265 | 'ALTER TABLE %s ADD CONSTRAINT "%s" FOREIGN KEY ("%s") REFERENCES %s ("%s") MATCH FULL ON DELETE %s ON UPDATE %s', |
||
| 266 | $this->buildTableName($details['table'], $details['schema']), $details['name'], |
||
| 267 | implode('","', $details['columns']), $this->buildTableName($details['foreign_table'], $details['foreign_schema']), |
||
| 268 | implode('","', $details['foreign_columns']), |
||
| 269 | $details['on_delete'] == '' ? 'NO ACTION' : $details['on_delete'], $details['on_update'] == '' ? 'NO ACTION' : $details['on_update'] |
||
| 270 | ) |
||
| 271 | ); |
||
| 272 | } |
||
| 273 | |||
| 274 | #[\Override] |
||
| 275 | protected function _dropForeignKey($details) |
||
| 276 | { |
||
| 277 | $this->dropKeyItem($details, 'foreign_keys'); |
||
| 278 | } |
||
| 279 | |||
| 280 | #[\Override] |
||
| 281 | protected function _addIndex($details) |
||
| 282 | { |
||
| 283 | $this->query( |
||
| 284 | sprintf( |
||
| 285 | 'CREATE INDEX %s "%s" ON %s ("%s")', $details['unique'] ? 'UNIQUE' : '', $details['name'], |
||
| 286 | $this->buildTableName($details['table'], $details['schema']), implode('", "', $details['columns']) |
||
| 287 | ) |
||
| 288 | ); |
||
| 289 | } |
||
| 290 | |||
| 291 | #[\Override] |
||
| 292 | protected function _dropIndex($details) |
||
| 293 | { |
||
| 294 | $this->query(sprintf('DROP INDEX %s', $this->buildTableName($details['name'], $details['schema']))); |
||
| 295 | } |
||
| 296 | |||
| 297 | #[\Override] |
||
| 301 | } |
||
| 302 | |||
| 303 | #[\Override] |
||
| 304 | public function convertTypes($type, $direction, $length = null) |
||
| 305 | { |
||
| 306 | $types = array( |
||
| 307 | 'integer' => 'integer', |
||
| 308 | 'bigint' => 'bigint', |
||
| 309 | 'character varying' => 'string', |
||
| 310 | 'numeric' => 'double', |
||
| 311 | 'timestamp with time zone' => 'timestamp', |
||
| 312 | 'timestamp without time zone' => 'timestamp', |
||
| 313 | 'text' => 'text', |
||
| 314 | 'boolean' => 'boolean', |
||
| 315 | 'date' => 'date', |
||
| 316 | 'bytea' => 'blob', |
||
| 317 | 'oid' => 'bigint' |
||
| 318 | ); |
||
| 319 | |||
| 320 | switch ($direction) { |
||
| 321 | case self::CONVERT_TO_YENTU: |
||
| 322 | $destinationType = $types[strtolower($type)]; |
||
| 323 | break; |
||
| 324 | |||
| 325 | case self::CONVERT_TO_DRIVER: |
||
| 326 | $destinationType = array_search(strtolower($type), $types); |
||
| 327 | break; |
||
| 328 | } |
||
| 329 | |||
| 330 | if ($destinationType == '') { |
||
| 331 | throw new \yentu\exceptions\DatabaseManipulatorException("Invalid data type {$type} requested"); |
||
| 332 | } else if ($destinationType == 'character varying') { |
||
| 333 | $destinationType .= $length === null ? '' : "($length)"; |
||
| 334 | } |
||
| 335 | |||
| 336 | return $destinationType; |
||
| 337 | } |
||
| 338 | |||
| 339 | #[\Override] |
||
| 345 | ) |
||
| 346 | ); |
||
| 347 | } |
||
| 348 | } |
||
| 349 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths