ntentan /
yentu
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace yentu\manipulators; |
||||
| 4 | |||||
| 5 | use yentu\Parameters; |
||||
| 6 | |||||
| 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); |
||||
|
0 ignored issues
–
show
|
|||||
| 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)); |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||||
| 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) |
||||
|
0 ignored issues
–
show
The parameter
$type is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. Loading history...
|
|||||
| 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] |
||||
| 298 | public function quoteIdentifier(string $identifier): string |
||||
| 299 | { |
||||
| 300 | return "\"$identifier\""; |
||||
| 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 == '') { |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
| 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] |
||||
| 340 | protected function _changeTableName($details) |
||||
| 341 | { |
||||
| 342 | $this->query(sprintf( |
||||
| 343 | "ALTER TABLE %s RENAME TO %s", $this->buildTableName($details['from']['name'], |
||||
| 344 | $details['from']['schema']), $this->buildTableName($details['to']['name'], false) |
||||
| 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