Completed
Branch feature/pre-split (1fb805)
by Anton
03:35
created

SQLServerHandler   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 0
loc 113
rs 10
c 0
b 0
f 0
wmc 16
lcom 1
cbo 7

5 Methods

Rating   Name   Duplication   Size   Complexity  
A renameTable() 0 4 1
A createColumn() 0 4 1
D alterColumn() 0 54 12
A renameColumn() 0 10 1
A dropIndex() 0 6 1
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\Database\Drivers\SQLServer;
8
9
use Spiral\Database\Drivers\SQLServer\Schemas\SQLServerColumn;
10
use Spiral\Database\Entities\AbstractHandler;
11
use Spiral\Database\Exceptions\SchemaException;
12
use Spiral\Database\Schemas\Prototypes\AbstractColumn;
13
use Spiral\Database\Schemas\Prototypes\AbstractIndex;
14
use Spiral\Database\Schemas\Prototypes\AbstractTable;
15
16
class SQLServerHandler extends AbstractHandler
17
{
18
    /**
19
     * {@inheritdoc}
20
     */
21
    public function renameTable(string $table, string $name)
22
    {
23
        $this->run('sp_rename @objname = ?, @newname = ?', [$table, $name]);
24
    }
25
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function createColumn(AbstractTable $table, AbstractColumn $column)
30
    {
31
        $this->run("ALTER TABLE {$this->identify($table)} ADD {$column->sqlStatement($this->driver)}");
32
    }
33
34
    /**
35
     * Driver specific column alter command.
36
     *
37
     * @param AbstractTable  $table
38
     * @param AbstractColumn $initial
39
     * @param AbstractColumn $column
40
     *
41
     * @throws SchemaException
42
     */
43
    public function alterColumn(
44
        AbstractTable $table,
45
        AbstractColumn $initial,
46
        AbstractColumn $column
47
    ) {
48
        if (!$initial instanceof SQLServerColumn || !$column instanceof SQLServerColumn) {
49
            throw new SchemaException('SQlServer handler can work only with SQLServer columns.');
50
        }
51
52
        //In SQLServer we have to drop ALL related indexes and foreign keys while
53
        //applying type change... yeah...
54
55
        $indexesBackup = [];
56
        $foreignBackup = [];
57
        foreach ($table->getIndexes() as $index) {
58
            if (in_array($column->getName(), $index->getColumns())) {
59
                $indexesBackup[] = $index;
60
                $this->dropIndex($table, $index);
61
            }
62
        }
63
64
        foreach ($table->getForeigns() as $foreign) {
65
            if ($column->getName() == $foreign->getColumn()) {
66
                $foreignBackup[] = $foreign;
67
                $this->dropForeign($table, $foreign);
68
            }
69
        }
70
71
        //Column will recreate needed constraints
72
        foreach ($column->getConstraints() as $constraint) {
73
            $this->dropConstrain($table, $constraint);
74
        }
75
76
        //Rename is separate operation
77
        if ($column->getName() != $initial->getName()) {
78
            $this->renameColumn($table, $initial, $column);
79
80
            //This call is required to correctly built set of alter operations
81
            $initial->setName($column->getName());
82
        }
83
84
        foreach ($column->alterOperations($this->driver, $initial) as $operation) {
85
            $this->run("ALTER TABLE {$this->identify($table)} {$operation}");
86
        }
87
88
        //Restoring indexes and foreign keys
89
        foreach ($indexesBackup as $index) {
90
            $this->createIndex($table, $index);
91
        }
92
93
        foreach ($foreignBackup as $foreign) {
94
            $this->createForeign($table, $foreign);
95
        }
96
    }
97
98
    /**
99
     * @param AbstractTable  $table
100
     * @param AbstractColumn $initial
101
     * @param AbstractColumn $column
102
     */
103
    private function renameColumn(
104
        AbstractTable $table,
105
        AbstractColumn $initial,
106
        AbstractColumn $column
107
    ) {
108
        $this->run("sp_rename ?, ?, 'COLUMN'", [
109
            $table->getName() . '.' . $initial->getName(),
110
            $column->getName()
111
        ]);
112
    }
113
114
    /**
115
     * Driver specific index remove (drop) command.
116
     *
117
     * @param AbstractTable $table
118
     * @param AbstractIndex $index
119
     *
120
     * @return self
121
     */
122
    public function dropIndex(AbstractTable $table, AbstractIndex $index)
123
    {
124
        $this->run("DROP INDEX {$index->getName(true)} ON {$table->getName(true)}");
0 ignored issues
show
Unused Code introduced by
The call to AbstractIndex::getName() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Unused Code introduced by
The call to AbstractTable::getName() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
125
126
        return $this;
127
    }
128
}