Total Complexity | 52 |
Total Lines | 350 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like OracleSchemaManager 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 OracleSchemaManager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class OracleSchemaManager extends AbstractSchemaManager |
||
28 | { |
||
29 | public function dropDatabase(string $database) : void |
||
52 | } |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * {@inheritdoc} |
||
57 | */ |
||
58 | protected function _getPortableViewDefinition(array $view) : View |
||
59 | { |
||
60 | $view = array_change_key_case($view, CASE_LOWER); |
||
61 | |||
62 | return new View($this->getQuotedIdentifierName($view['view_name']), $view['text']); |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * {@inheritdoc} |
||
67 | */ |
||
68 | protected function _getPortableUserDefinition(array $user) : array |
||
69 | { |
||
70 | $user = array_change_key_case($user, CASE_LOWER); |
||
71 | |||
72 | return [ |
||
73 | 'user' => $user['username'], |
||
74 | ]; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * {@inheritdoc} |
||
79 | */ |
||
80 | protected function _getPortableTableDefinition(array $table) : string |
||
81 | { |
||
82 | $table = array_change_key_case($table, CASE_LOWER); |
||
83 | |||
84 | return $this->getQuotedIdentifierName($table['table_name']); |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * {@inheritdoc} |
||
89 | * |
||
90 | * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html |
||
91 | */ |
||
92 | protected function _getPortableTableIndexesList(array $tableIndexRows, string $tableName) : array |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * {@inheritdoc} |
||
120 | */ |
||
121 | protected function _getPortableTableColumnDefinition(array $tableColumn) : Column |
||
122 | { |
||
123 | $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); |
||
124 | |||
125 | $dbType = strtolower($tableColumn['data_type']); |
||
126 | if (strpos($dbType, 'timestamp(') === 0) { |
||
127 | if (strpos($dbType, 'with time zone') !== false) { |
||
128 | $dbType = 'timestamptz'; |
||
129 | } else { |
||
130 | $dbType = 'timestamp'; |
||
131 | } |
||
132 | } |
||
133 | |||
134 | $length = $precision = null; |
||
135 | $scale = 0; |
||
136 | $fixed = false; |
||
137 | |||
138 | if (! isset($tableColumn['column_name'])) { |
||
139 | $tableColumn['column_name'] = ''; |
||
140 | } |
||
141 | |||
142 | // Default values returned from database sometimes have trailing spaces. |
||
143 | if ($tableColumn['data_default'] !== null) { |
||
144 | $tableColumn['data_default'] = trim($tableColumn['data_default']); |
||
145 | } |
||
146 | |||
147 | if ($tableColumn['data_default'] === '' || $tableColumn['data_default'] === 'NULL') { |
||
148 | $tableColumn['data_default'] = null; |
||
149 | } |
||
150 | |||
151 | if ($tableColumn['data_default'] !== null) { |
||
152 | // Default values returned from database are represented as literal expressions |
||
153 | if (preg_match('/^\'(.*)\'$/s', $tableColumn['data_default'], $matches) === 1) { |
||
154 | $tableColumn['data_default'] = str_replace("''", "'", $matches[1]); |
||
155 | } |
||
156 | } |
||
157 | |||
158 | if ($tableColumn['data_precision'] !== null) { |
||
159 | $precision = (int) $tableColumn['data_precision']; |
||
160 | } |
||
161 | |||
162 | if ($tableColumn['data_scale'] !== null) { |
||
163 | $scale = (int) $tableColumn['data_scale']; |
||
164 | } |
||
165 | |||
166 | $type = $this->extractDoctrineTypeFromComment($tableColumn['comments']) |
||
167 | ?? $this->_platform->getDoctrineTypeMapping($dbType); |
||
168 | |||
169 | switch ($dbType) { |
||
170 | case 'number': |
||
171 | if ($precision === 20 && $scale === 0) { |
||
172 | $type = 'bigint'; |
||
173 | } elseif ($precision === 5 && $scale === 0) { |
||
174 | $type = 'smallint'; |
||
175 | } elseif ($precision === 1 && $scale === 0) { |
||
176 | $type = 'boolean'; |
||
177 | } elseif ($scale > 0) { |
||
178 | $type = 'decimal'; |
||
179 | } |
||
180 | |||
181 | break; |
||
182 | |||
183 | case 'varchar': |
||
184 | case 'varchar2': |
||
185 | case 'nvarchar2': |
||
186 | $length = (int) $tableColumn['char_length']; |
||
187 | break; |
||
188 | |||
189 | case 'char': |
||
190 | case 'nchar': |
||
191 | $length = (int) $tableColumn['char_length']; |
||
192 | $fixed = true; |
||
193 | break; |
||
194 | } |
||
195 | |||
196 | $options = [ |
||
197 | 'notnull' => $tableColumn['nullable'] === 'N', |
||
198 | 'fixed' => $fixed, |
||
199 | 'default' => $tableColumn['data_default'], |
||
200 | 'length' => $length, |
||
201 | 'precision' => $precision, |
||
202 | 'scale' => $scale, |
||
203 | ]; |
||
204 | |||
205 | if (isset($tableColumn['comments'])) { |
||
206 | $options['comment'] = $tableColumn['comments']; |
||
207 | } |
||
208 | |||
209 | return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options); |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * {@inheritdoc} |
||
214 | */ |
||
215 | protected function _getPortableTableForeignKeysList(array $tableForeignKeys) : array |
||
216 | { |
||
217 | $list = []; |
||
218 | foreach ($tableForeignKeys as $value) { |
||
219 | $value = array_change_key_case($value, CASE_LOWER); |
||
220 | if (! isset($list[$value['constraint_name']])) { |
||
221 | if ($value['delete_rule'] === 'NO ACTION') { |
||
222 | $value['delete_rule'] = null; |
||
223 | } |
||
224 | |||
225 | $list[$value['constraint_name']] = [ |
||
226 | 'name' => $this->getQuotedIdentifierName($value['constraint_name']), |
||
227 | 'local' => [], |
||
228 | 'foreign' => [], |
||
229 | 'foreignTable' => $value['references_table'], |
||
230 | 'onDelete' => $value['delete_rule'], |
||
231 | ]; |
||
232 | } |
||
233 | |||
234 | $localColumn = $this->getQuotedIdentifierName($value['local_column']); |
||
235 | $foreignColumn = $this->getQuotedIdentifierName($value['foreign_column']); |
||
236 | |||
237 | $list[$value['constraint_name']]['local'][$value['position']] = $localColumn; |
||
238 | $list[$value['constraint_name']]['foreign'][$value['position']] = $foreignColumn; |
||
239 | } |
||
240 | |||
241 | $result = []; |
||
242 | foreach ($list as $constraint) { |
||
243 | $result[] = new ForeignKeyConstraint( |
||
244 | array_values($constraint['local']), |
||
245 | $this->getQuotedIdentifierName($constraint['foreignTable']), |
||
246 | array_values($constraint['foreign']), |
||
247 | $this->getQuotedIdentifierName($constraint['name']), |
||
248 | ['onDelete' => $constraint['onDelete']] |
||
249 | ); |
||
250 | } |
||
251 | |||
252 | return $result; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * {@inheritdoc} |
||
257 | */ |
||
258 | protected function _getPortableSequenceDefinition(array $sequence) : Sequence |
||
259 | { |
||
260 | $sequence = array_change_key_case($sequence, CASE_LOWER); |
||
261 | |||
262 | return new Sequence( |
||
263 | $this->getQuotedIdentifierName($sequence['sequence_name']), |
||
264 | (int) $sequence['increment_by'], |
||
265 | (int) $sequence['min_value'] |
||
266 | ); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * {@inheritdoc} |
||
271 | */ |
||
272 | protected function _getPortableDatabaseDefinition(array $database) : string |
||
273 | { |
||
274 | $database = array_change_key_case($database, CASE_LOWER); |
||
275 | |||
276 | return $database['username']; |
||
277 | } |
||
278 | |||
279 | public function createDatabase(string $database) : void |
||
280 | { |
||
281 | $params = $this->_conn->getParams(); |
||
282 | $username = $database; |
||
283 | $password = $params['password']; |
||
284 | |||
285 | $query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password; |
||
286 | $this->_conn->executeUpdate($query); |
||
287 | |||
288 | $query = 'GRANT DBA TO ' . $username; |
||
289 | $this->_conn->executeUpdate($query); |
||
290 | } |
||
291 | |||
292 | public function dropAutoincrement(string $table) : bool |
||
293 | { |
||
294 | assert($this->_platform instanceof OraclePlatform); |
||
295 | |||
296 | $sql = $this->_platform->getDropAutoincrementSql($table); |
||
297 | foreach ($sql as $query) { |
||
298 | $this->_conn->executeUpdate($query); |
||
299 | } |
||
300 | |||
301 | return true; |
||
302 | } |
||
303 | |||
304 | public function dropTable(string $name) : void |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Returns the quoted representation of the given identifier name. |
||
313 | * |
||
314 | * Quotes non-uppercase identifiers explicitly to preserve case |
||
315 | * and thus make references to the particular identifier work. |
||
316 | */ |
||
317 | private function getQuotedIdentifierName(string $identifier) : string |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Kills sessions connected with the given user. |
||
328 | * |
||
329 | * This is useful to force DROP USER operations which could fail because of active user sessions. |
||
330 | * |
||
331 | * @param string $user The name of the user to kill sessions for. |
||
332 | */ |
||
333 | private function killUserSessions(string $user) : void |
||
357 | ) |
||
358 | ); |
||
359 | } |
||
360 | } |
||
361 | |||
362 | public function listTableDetails(string $tableName) : Table |
||
379 |