Complex classes like QueryBuilder 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 QueryBuilder, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | class QueryBuilder extends \yii\db\QueryBuilder |
||
21 | { |
||
22 | |||
23 | /** |
||
24 | * @var array mapping from abstract column types (keys) to physical column types (values). |
||
25 | */ |
||
26 | public $typeMap = [ |
||
27 | Schema::TYPE_PK => 'integer NOT NULL PRIMARY KEY', |
||
28 | Schema::TYPE_UPK => 'integer NOT NULL PRIMARY KEY', |
||
29 | Schema::TYPE_BIGPK => 'bigint NOT NULL PRIMARY KEY', |
||
30 | Schema::TYPE_UBIGPK => 'bigint NOT NULL PRIMARY KEY', |
||
31 | Schema::TYPE_CHAR => 'char(1)', |
||
32 | Schema::TYPE_STRING => 'varchar(255)', |
||
33 | Schema::TYPE_TEXT => 'blob sub_type text', |
||
34 | Schema::TYPE_SMALLINT => 'smallint', |
||
35 | Schema::TYPE_INTEGER => 'integer', |
||
36 | Schema::TYPE_BIGINT => 'bigint', |
||
37 | Schema::TYPE_FLOAT => 'float', |
||
38 | Schema::TYPE_DOUBLE => 'double precision', |
||
39 | Schema::TYPE_DECIMAL => 'numeric(10,0)', |
||
40 | Schema::TYPE_DATETIME => 'timestamp', |
||
41 | Schema::TYPE_TIMESTAMP => 'timestamp', |
||
42 | Schema::TYPE_TIME => 'time', |
||
43 | Schema::TYPE_DATE => 'date', |
||
44 | Schema::TYPE_BINARY => 'blob', |
||
45 | Schema::TYPE_BOOLEAN => 'smallint', |
||
46 | Schema::TYPE_MONEY => 'numeric(18,4)', |
||
47 | ]; |
||
48 | |||
49 | /** |
||
50 | * Generates a SELECT SQL statement from a [[Query]] object. |
||
51 | * @param Query $query the [[Query]] object from which the SQL statement will be generated. |
||
52 | * @param array $params the parameters to be bound to the generated SQL statement. These parameters will |
||
53 | * be included in the result with the additional parameters generated during the query building process. |
||
54 | * @return array the generated SQL statement (the first array element) and the corresponding |
||
55 | * parameters to be bound to the SQL statement (the second array element). The parameters returned |
||
56 | * include those provided in `$params`. |
||
57 | */ |
||
58 | 175 | public function build($query, $params = []) |
|
98 | |||
99 | /** |
||
100 | * @inheritdoc |
||
101 | */ |
||
102 | 175 | public function buildSelect($columns, &$params, $distinct = false, $selectOption = null) |
|
121 | |||
122 | /** |
||
123 | * @inheritdoc |
||
124 | */ |
||
125 | 5 | protected function buildCompositeInCondition($operator, $columns, $values, &$params) |
|
147 | |||
148 | /** |
||
149 | * @inheritdoc |
||
150 | */ |
||
151 | 175 | public function buildOrderByAndLimit($sql, $orderBy, $limit, $offset) |
|
189 | |||
190 | /** |
||
191 | * @param array $unions |
||
192 | * @param array $params the binding parameters to be populated |
||
193 | * @return string the UNION clause built from [[Query::$union]]. |
||
194 | */ |
||
195 | 175 | public function buildUnion($unions, &$params) |
|
214 | |||
215 | /** |
||
216 | * |
||
217 | * @param Expression $value |
||
218 | * @return Expression |
||
219 | */ |
||
220 | 3 | protected function convertExpression($value) |
|
235 | |||
236 | /** |
||
237 | * @inheritdoc |
||
238 | */ |
||
239 | 22 | public function insert($table, $columns, &$params) |
|
268 | |||
269 | /** |
||
270 | * @inheritdoc |
||
271 | */ |
||
272 | 13 | public function update($table, $columns, $condition, &$params) |
|
289 | |||
290 | /** |
||
291 | * @inheritdoc |
||
292 | */ |
||
293 | 1 | public function batchInsert($table, $columns, $rows) |
|
332 | |||
333 | /** |
||
334 | * @inheritdoc |
||
335 | */ |
||
336 | 1 | public function renameTable($oldName, $newName) |
|
340 | |||
341 | /** |
||
342 | * @inheritdoc |
||
343 | */ |
||
344 | 2 | public function truncateTable($table) |
|
348 | |||
349 | /** |
||
350 | * @inheritdoc |
||
351 | */ |
||
352 | 1 | public function dropColumn($table, $column) |
|
357 | |||
358 | /** |
||
359 | * @inheritdoc |
||
360 | */ |
||
361 | 1 | public function renameColumn($table, $oldName, $newName) |
|
367 | |||
368 | /** |
||
369 | * @inheritdoc |
||
370 | */ |
||
371 | 3 | public function alterColumn($table, $column, $type) |
|
372 | { |
||
373 | 3 | $schema = $this->db->getSchema(); |
|
374 | 3 | $tableSchema = $schema->getTableSchema($table); |
|
375 | 3 | $columnSchema = $tableSchema->getColumn($column); |
|
376 | |||
377 | 3 | $allowNullNewType = !preg_match("/not +null/i", $type); |
|
378 | |||
379 | 3 | $type = preg_replace("/ +(not)? *null/i", "", $type); |
|
380 | |||
381 | 3 | $hasType = false; |
|
382 | |||
383 | 3 | $matches = []; |
|
384 | 3 | if (isset($this->typeMap[$type])) { |
|
385 | 2 | $hasType = true; |
|
386 | 3 | } elseif (preg_match('/^(\w+)[\( ]/', $type, $matches)) { |
|
387 | 2 | if (isset($this->typeMap[$matches[1]])) { |
|
388 | 2 | $hasType = true; |
|
389 | 2 | } |
|
390 | 2 | } |
|
391 | |||
392 | 3 | $baseSql = 'ALTER TABLE ' . $this->db->quoteTableName($table) |
|
393 | 3 | . ' ALTER ' . $this->db->quoteColumnName($column) |
|
394 | 3 | . (($hasType) ? ' TYPE ' : ' ') . $this->getColumnType($type); |
|
395 | |||
396 | 3 | if ($columnSchema->allowNull == $allowNullNewType) { |
|
397 | 2 | return $baseSql; |
|
398 | } else { |
||
399 | $sql = 'EXECUTE BLOCK AS BEGIN' |
||
400 | 2 | . ' EXECUTE STATEMENT ' . $this->db->quoteValue($baseSql) . ';' |
|
401 | 2 | . ' UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = ' . ($allowNullNewType ? 'NULL' : '1') |
|
402 | 2 | . ' WHERE UPPER(RDB$FIELD_NAME) = UPPER(\'' . $column . '\') AND UPPER(RDB$RELATION_NAME) = UPPER(\'' . $table . '\');'; |
|
403 | /** |
||
404 | * In any case (whichever option you choose), make sure that the column doesn't have any NULLs. |
||
405 | * Firebird will not check it for you. Later when you backup the database, everything is fine, |
||
406 | * but restore will fail as the NOT NULL column has NULLs in it. To be safe, each time you change from NULL to NOT NULL. |
||
407 | */ |
||
408 | 2 | if (!$allowNullNewType) { |
|
409 | 2 | $sql .= ' UPDATE ' . $this->db->quoteTableName($table) . ' SET ' . $this->db->quoteColumnName($column) . ' = 0' |
|
410 | 2 | . ' WHERE ' . $this->db->quoteColumnName($column) . ' IS NULL;'; |
|
411 | 2 | } |
|
412 | 2 | $sql .= ' END'; |
|
413 | 2 | return $sql; |
|
414 | } |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * @inheritdoc |
||
419 | */ |
||
420 | 1 | public function dropIndex($name, $table) |
|
424 | |||
425 | /** |
||
426 | * @inheritdoc |
||
427 | */ |
||
428 | 1 | public function resetSequence($table, $value = null) |
|
459 | |||
460 | /** |
||
461 | * @inheritdoc |
||
462 | */ |
||
463 | 5 | public function createTable($table, $columns, $options = null) |
|
497 | |||
498 | /** |
||
499 | * @inheritdoc |
||
500 | */ |
||
501 | 3 | public function dropTable($table) |
|
520 | |||
521 | /** |
||
522 | * Creates a SELECT EXISTS() SQL statement. |
||
523 | * @param string $rawSql the subquery in a raw form to select from. |
||
524 | * @return string the SELECT EXISTS() SQL statement. |
||
525 | * |
||
526 | * @since 2.0.8 |
||
527 | */ |
||
528 | 3 | public function selectExists($rawSql) |
|
532 | } |
||
533 |