Completed
Pull Request — master (#29151)
by Piotr
08:58
created

OracleMigrator::quoteForeignKeyConstraint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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