Passed
Push — master ( 459e0b...37feee )
by Morris
12:59 queued 12s
created

OracleMigrator::convertStatementToScript()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Christoph Wurst <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Jörn Friedrich Dreyer <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Piotr Mrowczynski <[email protected]>
10
 * @author Robin Appelman <[email protected]>
11
 * @author Roeland Jago Douma <[email protected]>
12
 * @author Thomas Müller <[email protected]>
13
 * @author Victor Dubiniuk <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program. If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
31
namespace OC\DB;
32
33
use Doctrine\DBAL\Exception;
34
use Doctrine\DBAL\Schema\Column;
35
use Doctrine\DBAL\Schema\ColumnDiff;
36
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
37
use Doctrine\DBAL\Schema\Index;
38
use Doctrine\DBAL\Schema\Schema;
39
use Doctrine\DBAL\Schema\Table;
40
41
class OracleMigrator extends Migrator {
42
43
	/**
44
	 * Quote a column's name but changing the name requires recreating
45
	 * the column instance and copying over all properties.
46
	 *
47
	 * @param Column $column old column
48
	 * @return Column new column instance with new name
49
	 */
50
	protected function quoteColumn(Column $column) {
51
		$newColumn = new Column(
52
			$this->connection->quoteIdentifier($column->getName()),
53
			$column->getType()
54
		);
55
		$newColumn->setAutoincrement($column->getAutoincrement());
56
		$newColumn->setColumnDefinition($column->getColumnDefinition());
57
		$newColumn->setComment($column->getComment());
58
		$newColumn->setDefault($column->getDefault());
59
		$newColumn->setFixed($column->getFixed());
60
		$newColumn->setLength($column->getLength());
61
		$newColumn->setNotnull($column->getNotnull());
62
		$newColumn->setPrecision($column->getPrecision());
63
		$newColumn->setScale($column->getScale());
64
		$newColumn->setUnsigned($column->getUnsigned());
65
		$newColumn->setPlatformOptions($column->getPlatformOptions());
66
		$newColumn->setCustomSchemaOptions($column->getPlatformOptions());
67
		return $newColumn;
68
	}
69
70
	/**
71
	 * Quote an index's name but changing the name requires recreating
72
	 * the index instance and copying over all properties.
73
	 *
74
	 * @param Index $index old index
75
	 * @return Index new index instance with new name
76
	 */
77
	protected function quoteIndex($index) {
78
		return new Index(
79
		//TODO migrate existing uppercase indexes, then $this->connection->quoteIdentifier($index->getName()),
80
			$index->getName(),
81
			array_map(function ($columnName) {
82
				return $this->connection->quoteIdentifier($columnName);
83
			}, $index->getColumns()),
84
			$index->isUnique(),
85
			$index->isPrimary(),
86
			$index->getFlags(),
87
			$index->getOptions()
88
		);
89
	}
90
91
	/**
92
	 * Quote an ForeignKeyConstraint's name but changing the name requires recreating
93
	 * the ForeignKeyConstraint instance and copying over all properties.
94
	 *
95
	 * @param ForeignKeyConstraint $fkc old fkc
96
	 * @return ForeignKeyConstraint new fkc instance with new name
97
	 */
98
	protected function quoteForeignKeyConstraint($fkc) {
99
		return new ForeignKeyConstraint(
100
			array_map(function ($columnName) {
101
				return $this->connection->quoteIdentifier($columnName);
102
			}, $fkc->getLocalColumns()),
103
			$this->connection->quoteIdentifier($fkc->getForeignTableName()),
104
			array_map(function ($columnName) {
105
				return $this->connection->quoteIdentifier($columnName);
106
			}, $fkc->getForeignColumns()),
107
			$fkc->getName(),
108
			$fkc->getOptions()
109
		);
110
	}
111
112
	/**
113
	 * @param Schema $targetSchema
114
	 * @param \Doctrine\DBAL\Connection $connection
115
	 * @return \Doctrine\DBAL\Schema\SchemaDiff
116
	 * @throws Exception
117
	 */
118
	protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
119
		$schemaDiff = parent::getDiff($targetSchema, $connection);
120
121
		// oracle forces us to quote the identifiers
122
		$schemaDiff->newTables = array_map(function (Table $table) {
123
			return new Table(
124
				$this->connection->quoteIdentifier($table->getName()),
125
				array_map(function (Column $column) {
126
					return $this->quoteColumn($column);
127
				}, $table->getColumns()),
128
				array_map(function (Index $index) {
129
					return $this->quoteIndex($index);
130
				}, $table->getIndexes()),
131
				[],
132
				array_map(function (ForeignKeyConstraint $fck) {
133
					return $this->quoteForeignKeyConstraint($fck);
134
				}, $table->getForeignKeys()),
135
				$table->getOptions()
136
			);
137
		}, $schemaDiff->newTables);
138
139
		$schemaDiff->removedTables = array_map(function (Table $table) {
140
			return new Table(
141
				$this->connection->quoteIdentifier($table->getName()),
142
				$table->getColumns(),
143
				$table->getIndexes(),
144
				[],
145
				$table->getForeignKeys(),
146
				$table->getOptions()
147
			);
148
		}, $schemaDiff->removedTables);
149
150
		foreach ($schemaDiff->changedTables as $tableDiff) {
151
			$tableDiff->name = $this->connection->quoteIdentifier($tableDiff->name);
152
153
			$tableDiff->addedColumns = array_map(function (Column $column) {
154
				return $this->quoteColumn($column);
155
			}, $tableDiff->addedColumns);
156
157
			foreach ($tableDiff->changedColumns as $column) {
158
				$column->oldColumnName = $this->connection->quoteIdentifier($column->oldColumnName);
159
				// auto increment is not relevant for oracle and can anyhow not be applied on change
160
				$column->changedProperties = array_diff($column->changedProperties, ['autoincrement', 'unsigned']);
161
			}
162
			// remove columns that no longer have changed (because autoincrement and unsigned are not supported)
163
			$tableDiff->changedColumns = array_filter($tableDiff->changedColumns, function (ColumnDiff $column) {
164
				return count($column->changedProperties) > 0;
165
			});
166
167
			$tableDiff->removedColumns = array_map(function (Column $column) {
168
				return $this->quoteColumn($column);
169
			}, $tableDiff->removedColumns);
170
171
			$tableDiff->renamedColumns = array_map(function (Column $column) {
172
				return $this->quoteColumn($column);
173
			}, $tableDiff->renamedColumns);
174
175
			$tableDiff->addedIndexes = array_map(function (Index $index) {
176
				return $this->quoteIndex($index);
177
			}, $tableDiff->addedIndexes);
178
179
			$tableDiff->changedIndexes = array_map(function (Index $index) {
180
				return $this->quoteIndex($index);
181
			}, $tableDiff->changedIndexes);
182
183
			$tableDiff->removedIndexes = array_map(function (Index $index) {
184
				return $this->quoteIndex($index);
185
			}, $tableDiff->removedIndexes);
186
187
			$tableDiff->renamedIndexes = array_map(function (Index $index) {
188
				return $this->quoteIndex($index);
189
			}, $tableDiff->renamedIndexes);
190
191
			$tableDiff->addedForeignKeys = array_map(function (ForeignKeyConstraint $fkc) {
192
				return $this->quoteForeignKeyConstraint($fkc);
193
			}, $tableDiff->addedForeignKeys);
194
195
			$tableDiff->changedForeignKeys = array_map(function (ForeignKeyConstraint $fkc) {
196
				return $this->quoteForeignKeyConstraint($fkc);
197
			}, $tableDiff->changedForeignKeys);
198
199
			$tableDiff->removedForeignKeys = array_map(function (ForeignKeyConstraint $fkc) {
200
				return $this->quoteForeignKeyConstraint($fkc);
201
			}, $tableDiff->removedForeignKeys);
202
		}
203
204
		return $schemaDiff;
205
	}
206
207
	/**
208
	 * @param $statement
209
	 * @return string
210
	 */
211
	protected function convertStatementToScript($statement) {
212
		if (substr($statement, -1) === ';') {
213
			return $statement . PHP_EOL . '/' . PHP_EOL;
214
		}
215
		$script = $statement . ';';
216
		$script .= PHP_EOL;
217
		$script .= PHP_EOL;
218
		return $script;
219
	}
220
221
	protected function getFilterExpression() {
222
		return '/^"' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/';
223
	}
224
}
225