Completed
Branch feature/pre-split (92bc7d)
by Anton
04:30
created

AbstractCommander::alterColumn()

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 5
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Database\Schemas;
10
11
use Spiral\Database\Entities\Driver;
12
13
/**
14
 * Holds set of DBMS specific element operations.
15
 *
16
 * @todo deprecate in order to replace with Phinx and/or migration engine
17
 */
18
abstract class AbstractCommander
19
{
20
    /**
21
     * @var Driver
22
     */
23
    private $driver = null;
24
25
    /**
26
     * @param Driver $driver
27
     */
28
    public function __construct(Driver $driver)
29
    {
30
        $this->driver = $driver;
31
    }
32
33
    /**
34
     * Associated driver.
35
     *
36
     * @return Driver
37
     */
38
    public function getDriver(): Driver
39
    {
40
        return $this->driver;
41
    }
42
43
    /**
44
     * Create table!
45
     *
46
     * @param AbstractTable $table
47
     *
48
     * @return self
49
     */
50
    public function createTable(AbstractTable $table): AbstractCommander
51
    {
52
        //Executing!
53
        $this->run($this->createStatement($table));
54
55
        //Not all databases support adding index while table creation, so we can do it after
56
        foreach ($table->getIndexes() as $index) {
57
            $this->addIndex($table, $index);
58
        }
59
60
        return $this;
61
    }
62
63
    /**
64
     * Drop table from database.
65
     *
66
     * @param string $table
67
     */
68
    public function dropTable(string $table)
69
    {
70
        $this->run("DROP TABLE {$this->quote($table)}");
71
    }
72
73
    /**
74
     * Rename table from one name to another.
75
     *
76
     * @param string $table
77
     * @param string $name
78
     *
79
     * @return self
80
     */
81
    public function renameTable(string $table, string $name): AbstractCommander
82
    {
83
        $this->run("ALTER TABLE {$this->quote($table)} RENAME TO {$this->quote($name)}");
84
85
        return $this;
86
    }
87
88
    /**
89
     * Driver specific column add command.
90
     *
91
     * @param AbstractTable  $table
92
     * @param AbstractColumn $column
93
     *
94
     * @return self
95
     */
96
    public function addColumn(AbstractTable $table, AbstractColumn $column): AbstractCommander
97
    {
98
        $this->run("ALTER TABLE {$table->getName(true)} ADD COLUMN {$column->sqlStatement()}");
99
100
        return $this;
101
    }
102
103
    /**
104
     * Driver specific column remove (drop) command.
105
     *
106
     * @param AbstractTable  $table
107
     * @param AbstractColumn $column
108
     *
109
     * @return self
110
     */
111
    public function dropColumn(AbstractTable $table, AbstractColumn $column): AbstractCommander
112
    {
113
        foreach ($column->getConstraints() as $constraint) {
114
            //We have to erase all associated constraints
115
            $this->dropConstrain($table, $constraint);
116
        }
117
118
        $this->run("ALTER TABLE {$table->getName(true)} DROP COLUMN {$column->getName(true)}");
119
120
        return $this;
121
    }
122
123
    /**
124
     * Driver specific column alter command.
125
     *
126
     * @param AbstractTable  $table
127
     * @param AbstractColumn $initial
128
     * @param AbstractColumn $column
129
     *
130
     * @return self
131
     */
132
    abstract public function alterColumn(
133
        AbstractTable $table,
134
        AbstractColumn $initial,
135
        AbstractColumn $column
136
    ): AbstractCommander;
137
138
    /**
139
     * Driver specific index adding command.
140
     *
141
     * @param AbstractTable $table
142
     * @param AbstractIndex $index
143
     *
144
     * @return self
145
     */
146
    public function addIndex(AbstractTable $table, AbstractIndex $index): AbstractCommander
0 ignored issues
show
Unused Code introduced by
The parameter $table is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
147
    {
148
        $this->run("CREATE {$index->sqlStatement()}");
149
150
        return $this;
151
    }
152
153
    /**
154
     * Driver specific index remove (drop) command.
155
     *
156
     * @param AbstractTable $table
157
     * @param AbstractIndex $index
158
     *
159
     * @return self
160
     */
161
    public function dropIndex(AbstractTable $table, AbstractIndex $index): AbstractCommander
162
    {
163
        $this->run("DROP INDEX {$index->getName(true)}");
164
165
        return $this;
166
    }
167
168
    /**
169
     * Driver specific index alter command, by default it will remove and add index.
170
     *
171
     * @param AbstractTable $table
172
     * @param AbstractIndex $initial
173
     * @param AbstractIndex $index
174
     *
175
     * @return self
176
     */
177
    public function alterIndex(
178
        AbstractTable $table,
179
        AbstractIndex $initial,
180
        AbstractIndex $index
181
    ): AbstractCommander {
182
        return $this->dropIndex($table, $initial)->addIndex($table, $index);
183
    }
184
185
    /**
186
     * Driver specific foreign key adding command.
187
     *
188
     * @param AbstractTable     $table
189
     * @param AbstractReference $foreign
190
     *
191
     * @return self
192
     */
193
    public function addForeign(AbstractTable $table, AbstractReference $foreign): AbstractCommander
194
    {
195
        $this->run("ALTER TABLE {$table->getName(true)} ADD {$foreign->sqlStatement()}");
196
197
        return $this;
198
    }
199
200
    /**
201
     * Driver specific foreign key remove (drop) command.
202
     *
203
     * @param AbstractTable     $table
204
     * @param AbstractReference $foreign
205
     *
206
     * @return self
207
     */
208
    public function dropForeign(AbstractTable $table, AbstractReference $foreign): AbstractCommander
209
    {
210
        return $this->dropConstrain($table, $foreign->getName());
211
    }
212
213
    /**
214
     * Driver specific foreign key alter command, by default it will remove and add foreign key.
215
     *
216
     * @param AbstractTable     $table
217
     * @param AbstractReference $initial
218
     * @param AbstractReference $foreign
219
     *
220
     * @return self
221
     */
222
    public function alterForeign(
223
        AbstractTable $table,
224
        AbstractReference $initial,
225
        AbstractReference $foreign
226
    ): AbstractCommander {
227
        return $this->dropForeign($table, $initial)->addForeign($table, $foreign);
228
    }
229
230
    /**
231
     * Drop column constraint using it's name.
232
     *
233
     * @param AbstractTable $table
234
     * @param string        $constraint
235
     *
236
     * @return self
237
     */
238
    public function dropConstrain(AbstractTable $table, string $constraint): AbstractCommander
239
    {
240
        $this->run("ALTER TABLE {$table->getName(true)} DROP CONSTRAINT {$this->quote($constraint)}");
241
242
        return $this;
243
    }
244
245
    /**
246
     * Execute statement.
247
     *
248
     * @param string $statement
249
     * @param array  $parameters
250
     *
251
     * @return \PDOStatement
252
     */
253
    protected function run(string $statement, array $parameters = []): \PDOStatement
254
    {
255
        return $this->driver->statement($statement, $parameters);
256
    }
257
258
    /**
259
     * Quote identifier.
260
     *
261
     * @param string $identifier
262
     *
263
     * @return string
264
     */
265
    protected function quote(string $identifier): string
266
    {
267
        return $this->driver->identifier($identifier);
268
    }
269
270
    /**
271
     * Get statement needed to create table.
272
     *
273
     * @param AbstractTable $table
274
     *
275
     * @return string
276
     */
277
    protected function createStatement(AbstractTable $table): string
278
    {
279
        $statement = ["CREATE TABLE {$table->getName(true)} ("];
280
        $innerStatement = [];
281
282
        //Columns
283
        foreach ($table->getColumns() as $column) {
284
            $innerStatement[] = $column->sqlStatement();
285
        }
286
287
        //Primary key
288
        if (!empty($table->getPrimaryKeys())) {
289
            $primaryKeys = array_map([$this, 'quote'], $table->getPrimaryKeys());
290
291
            $innerStatement[] = 'PRIMARY KEY (' . implode(', ', $primaryKeys) . ')';
292
        }
293
294
        //Constraints and foreign keys
295
        foreach ($table->getForeigns() as $reference) {
296
            $innerStatement[] = $reference->sqlStatement();
297
        }
298
299
        $statement[] = '    ' . implode(",\n    ", $innerStatement);
300
        $statement[] = ')';
301
302
        return implode("\n", $statement);
303
    }
304
}
305