Passed
Push — master ( ce430c...74f361 )
by Roeland
13:44 queued 10s
created
lib/private/DB/Migrator.php 1 patch
Indentation   +261 added lines, -261 removed lines patch added patch discarded remove patch
@@ -49,265 +49,265 @@
 block discarded – undo
49 49
 
50 50
 class Migrator {
51 51
 
52
-	/** @var \Doctrine\DBAL\Connection */
53
-	protected $connection;
54
-
55
-	/** @var ISecureRandom */
56
-	private $random;
57
-
58
-	/** @var IConfig */
59
-	protected $config;
60
-
61
-	/** @var EventDispatcherInterface  */
62
-	private $dispatcher;
63
-
64
-	/** @var bool */
65
-	private $noEmit = false;
66
-
67
-	/**
68
-	 * @param \Doctrine\DBAL\Connection $connection
69
-	 * @param ISecureRandom $random
70
-	 * @param IConfig $config
71
-	 * @param EventDispatcherInterface $dispatcher
72
-	 */
73
-	public function __construct(\Doctrine\DBAL\Connection $connection,
74
-								ISecureRandom $random,
75
-								IConfig $config,
76
-								EventDispatcherInterface $dispatcher = null) {
77
-		$this->connection = $connection;
78
-		$this->random = $random;
79
-		$this->config = $config;
80
-		$this->dispatcher = $dispatcher;
81
-	}
82
-
83
-	/**
84
-	 * @param \Doctrine\DBAL\Schema\Schema $targetSchema
85
-	 *
86
-	 * @throws Exception
87
-	 */
88
-	public function migrate(Schema $targetSchema) {
89
-		$this->noEmit = true;
90
-		$this->applySchema($targetSchema);
91
-	}
92
-
93
-	/**
94
-	 * @param \Doctrine\DBAL\Schema\Schema $targetSchema
95
-	 * @return string
96
-	 */
97
-	public function generateChangeScript(Schema $targetSchema) {
98
-		$schemaDiff = $this->getDiff($targetSchema, $this->connection);
99
-
100
-		$script = '';
101
-		$sqls = $schemaDiff->toSql($this->connection->getDatabasePlatform());
102
-		foreach ($sqls as $sql) {
103
-			$script .= $this->convertStatementToScript($sql);
104
-		}
105
-
106
-		return $script;
107
-	}
108
-
109
-	/**
110
-	 * Create a unique name for the temporary table
111
-	 *
112
-	 * @param string $name
113
-	 * @return string
114
-	 */
115
-	protected function generateTemporaryTableName($name) {
116
-		return $this->config->getSystemValue('dbtableprefix', 'oc_') . $name . '_' . $this->random->generate(13, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS);
117
-	}
118
-
119
-	/**
120
-	 * Check the migration of a table on a copy so we can detect errors before messing with the real table
121
-	 *
122
-	 * @param \Doctrine\DBAL\Schema\Table $table
123
-	 * @throws \OC\DB\MigrationException
124
-	 */
125
-	protected function checkTableMigrate(Table $table) {
126
-		$name = $table->getName();
127
-		$tmpName = $this->generateTemporaryTableName($name);
128
-
129
-		$this->copyTable($name, $tmpName);
130
-
131
-		//create the migration schema for the temporary table
132
-		$tmpTable = $this->renameTableSchema($table, $tmpName);
133
-		$schemaConfig = new SchemaConfig();
134
-		$schemaConfig->setName($this->connection->getDatabase());
135
-		$schema = new Schema([$tmpTable], [], $schemaConfig);
136
-
137
-		try {
138
-			$this->applySchema($schema);
139
-			$this->dropTable($tmpName);
140
-		} catch (Exception $e) {
141
-			// pgsql needs to commit it's failed transaction before doing anything else
142
-			if ($this->connection->isTransactionActive()) {
143
-				$this->connection->commit();
144
-			}
145
-			$this->dropTable($tmpName);
146
-			throw new MigrationException($table->getName(), $e->getMessage());
147
-		}
148
-	}
149
-
150
-	/**
151
-	 * @param \Doctrine\DBAL\Schema\Table $table
152
-	 * @param string $newName
153
-	 * @return \Doctrine\DBAL\Schema\Table
154
-	 */
155
-	protected function renameTableSchema(Table $table, $newName) {
156
-		/**
157
-		 * @var \Doctrine\DBAL\Schema\Index[] $indexes
158
-		 */
159
-		$indexes = $table->getIndexes();
160
-		$newIndexes = [];
161
-		foreach ($indexes as $index) {
162
-			if ($index->isPrimary()) {
163
-				// do not rename primary key
164
-				$indexName = $index->getName();
165
-			} else {
166
-				// avoid conflicts in index names
167
-				$indexName = $this->config->getSystemValue('dbtableprefix', 'oc_') . $this->random->generate(13, ISecureRandom::CHAR_LOWER);
168
-			}
169
-			$newIndexes[] = new Index($indexName, $index->getColumns(), $index->isUnique(), $index->isPrimary());
170
-		}
171
-
172
-		// foreign keys are not supported so we just set it to an empty array
173
-		return new Table($newName, $table->getColumns(), $newIndexes, [], [], $table->getOptions());
174
-	}
175
-
176
-	/**
177
-	 * @throws Exception
178
-	 */
179
-	public function createSchema() {
180
-		$this->connection->getConfiguration()->setSchemaAssetsFilter(function ($asset) {
181
-			/** @var string|AbstractAsset $asset */
182
-			$filterExpression = $this->getFilterExpression();
183
-			if ($asset instanceof AbstractAsset) {
184
-				return preg_match($filterExpression, $asset->getName()) === 1;
185
-			}
186
-			return preg_match($filterExpression, $asset) === 1;
187
-		});
188
-		return $this->connection->getSchemaManager()->createSchema();
189
-	}
190
-
191
-	/**
192
-	 * @param Schema $targetSchema
193
-	 * @param \Doctrine\DBAL\Connection $connection
194
-	 * @return \Doctrine\DBAL\Schema\SchemaDiff
195
-	 */
196
-	protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
197
-		// adjust varchar columns with a length higher then getVarcharMaxLength to clob
198
-		foreach ($targetSchema->getTables() as $table) {
199
-			foreach ($table->getColumns() as $column) {
200
-				if ($column->getType() instanceof StringType) {
201
-					if ($column->getLength() > $connection->getDatabasePlatform()->getVarcharMaxLength()) {
202
-						$column->setType(Type::getType('text'));
203
-						$column->setLength(null);
204
-					}
205
-				}
206
-			}
207
-		}
208
-
209
-		$this->connection->getConfiguration()->setSchemaAssetsFilter(function ($asset) {
210
-			/** @var string|AbstractAsset $asset */
211
-			$filterExpression = $this->getFilterExpression();
212
-			if ($asset instanceof AbstractAsset) {
213
-				return preg_match($filterExpression, $asset->getName()) === 1;
214
-			}
215
-			return preg_match($filterExpression, $asset) === 1;
216
-		});
217
-		$sourceSchema = $connection->getSchemaManager()->createSchema();
218
-
219
-		// remove tables we don't know about
220
-		foreach ($sourceSchema->getTables() as $table) {
221
-			if (!$targetSchema->hasTable($table->getName())) {
222
-				$sourceSchema->dropTable($table->getName());
223
-			}
224
-		}
225
-		// remove sequences we don't know about
226
-		foreach ($sourceSchema->getSequences() as $table) {
227
-			if (!$targetSchema->hasSequence($table->getName())) {
228
-				$sourceSchema->dropSequence($table->getName());
229
-			}
230
-		}
231
-
232
-		$comparator = new Comparator();
233
-		return $comparator->compare($sourceSchema, $targetSchema);
234
-	}
235
-
236
-	/**
237
-	 * @param \Doctrine\DBAL\Schema\Schema $targetSchema
238
-	 * @param \Doctrine\DBAL\Connection $connection
239
-	 *
240
-	 * @throws Exception
241
-	 */
242
-	protected function applySchema(Schema $targetSchema, \Doctrine\DBAL\Connection $connection = null) {
243
-		if (is_null($connection)) {
244
-			$connection = $this->connection;
245
-		}
246
-
247
-		$schemaDiff = $this->getDiff($targetSchema, $connection);
248
-
249
-		if (!$connection->getDatabasePlatform() instanceof MySQLPlatform) {
250
-			$connection->beginTransaction();
251
-		}
252
-		$sqls = $schemaDiff->toSql($connection->getDatabasePlatform());
253
-		$step = 0;
254
-		foreach ($sqls as $sql) {
255
-			$this->emit($sql, $step++, count($sqls));
256
-			$connection->query($sql);
257
-		}
258
-		if (!$connection->getDatabasePlatform() instanceof MySQLPlatform) {
259
-			$connection->commit();
260
-		}
261
-	}
262
-
263
-	/**
264
-	 * @param string $sourceName
265
-	 * @param string $targetName
266
-	 */
267
-	protected function copyTable($sourceName, $targetName) {
268
-		$quotedSource = $this->connection->quoteIdentifier($sourceName);
269
-		$quotedTarget = $this->connection->quoteIdentifier($targetName);
270
-
271
-		$this->connection->exec('CREATE TABLE ' . $quotedTarget . ' (LIKE ' . $quotedSource . ')');
272
-		$this->connection->exec('INSERT INTO ' . $quotedTarget . ' SELECT * FROM ' . $quotedSource);
273
-	}
274
-
275
-	/**
276
-	 * @param string $name
277
-	 */
278
-	protected function dropTable($name) {
279
-		$this->connection->exec('DROP TABLE ' . $this->connection->quoteIdentifier($name));
280
-	}
281
-
282
-	/**
283
-	 * @param $statement
284
-	 * @return string
285
-	 */
286
-	protected function convertStatementToScript($statement) {
287
-		$script = $statement . ';';
288
-		$script .= PHP_EOL;
289
-		$script .= PHP_EOL;
290
-		return $script;
291
-	}
292
-
293
-	protected function getFilterExpression() {
294
-		return '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/';
295
-	}
296
-
297
-	protected function emit($sql, $step, $max) {
298
-		if ($this->noEmit) {
299
-			return;
300
-		}
301
-		if (is_null($this->dispatcher)) {
302
-			return;
303
-		}
304
-		$this->dispatcher->dispatch('\OC\DB\Migrator::executeSql', new GenericEvent($sql, [$step + 1, $max]));
305
-	}
306
-
307
-	private function emitCheckStep($tableName, $step, $max) {
308
-		if (is_null($this->dispatcher)) {
309
-			return;
310
-		}
311
-		$this->dispatcher->dispatch('\OC\DB\Migrator::checkTable', new GenericEvent($tableName, [$step + 1, $max]));
312
-	}
52
+    /** @var \Doctrine\DBAL\Connection */
53
+    protected $connection;
54
+
55
+    /** @var ISecureRandom */
56
+    private $random;
57
+
58
+    /** @var IConfig */
59
+    protected $config;
60
+
61
+    /** @var EventDispatcherInterface  */
62
+    private $dispatcher;
63
+
64
+    /** @var bool */
65
+    private $noEmit = false;
66
+
67
+    /**
68
+     * @param \Doctrine\DBAL\Connection $connection
69
+     * @param ISecureRandom $random
70
+     * @param IConfig $config
71
+     * @param EventDispatcherInterface $dispatcher
72
+     */
73
+    public function __construct(\Doctrine\DBAL\Connection $connection,
74
+                                ISecureRandom $random,
75
+                                IConfig $config,
76
+                                EventDispatcherInterface $dispatcher = null) {
77
+        $this->connection = $connection;
78
+        $this->random = $random;
79
+        $this->config = $config;
80
+        $this->dispatcher = $dispatcher;
81
+    }
82
+
83
+    /**
84
+     * @param \Doctrine\DBAL\Schema\Schema $targetSchema
85
+     *
86
+     * @throws Exception
87
+     */
88
+    public function migrate(Schema $targetSchema) {
89
+        $this->noEmit = true;
90
+        $this->applySchema($targetSchema);
91
+    }
92
+
93
+    /**
94
+     * @param \Doctrine\DBAL\Schema\Schema $targetSchema
95
+     * @return string
96
+     */
97
+    public function generateChangeScript(Schema $targetSchema) {
98
+        $schemaDiff = $this->getDiff($targetSchema, $this->connection);
99
+
100
+        $script = '';
101
+        $sqls = $schemaDiff->toSql($this->connection->getDatabasePlatform());
102
+        foreach ($sqls as $sql) {
103
+            $script .= $this->convertStatementToScript($sql);
104
+        }
105
+
106
+        return $script;
107
+    }
108
+
109
+    /**
110
+     * Create a unique name for the temporary table
111
+     *
112
+     * @param string $name
113
+     * @return string
114
+     */
115
+    protected function generateTemporaryTableName($name) {
116
+        return $this->config->getSystemValue('dbtableprefix', 'oc_') . $name . '_' . $this->random->generate(13, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS);
117
+    }
118
+
119
+    /**
120
+     * Check the migration of a table on a copy so we can detect errors before messing with the real table
121
+     *
122
+     * @param \Doctrine\DBAL\Schema\Table $table
123
+     * @throws \OC\DB\MigrationException
124
+     */
125
+    protected function checkTableMigrate(Table $table) {
126
+        $name = $table->getName();
127
+        $tmpName = $this->generateTemporaryTableName($name);
128
+
129
+        $this->copyTable($name, $tmpName);
130
+
131
+        //create the migration schema for the temporary table
132
+        $tmpTable = $this->renameTableSchema($table, $tmpName);
133
+        $schemaConfig = new SchemaConfig();
134
+        $schemaConfig->setName($this->connection->getDatabase());
135
+        $schema = new Schema([$tmpTable], [], $schemaConfig);
136
+
137
+        try {
138
+            $this->applySchema($schema);
139
+            $this->dropTable($tmpName);
140
+        } catch (Exception $e) {
141
+            // pgsql needs to commit it's failed transaction before doing anything else
142
+            if ($this->connection->isTransactionActive()) {
143
+                $this->connection->commit();
144
+            }
145
+            $this->dropTable($tmpName);
146
+            throw new MigrationException($table->getName(), $e->getMessage());
147
+        }
148
+    }
149
+
150
+    /**
151
+     * @param \Doctrine\DBAL\Schema\Table $table
152
+     * @param string $newName
153
+     * @return \Doctrine\DBAL\Schema\Table
154
+     */
155
+    protected function renameTableSchema(Table $table, $newName) {
156
+        /**
157
+         * @var \Doctrine\DBAL\Schema\Index[] $indexes
158
+         */
159
+        $indexes = $table->getIndexes();
160
+        $newIndexes = [];
161
+        foreach ($indexes as $index) {
162
+            if ($index->isPrimary()) {
163
+                // do not rename primary key
164
+                $indexName = $index->getName();
165
+            } else {
166
+                // avoid conflicts in index names
167
+                $indexName = $this->config->getSystemValue('dbtableprefix', 'oc_') . $this->random->generate(13, ISecureRandom::CHAR_LOWER);
168
+            }
169
+            $newIndexes[] = new Index($indexName, $index->getColumns(), $index->isUnique(), $index->isPrimary());
170
+        }
171
+
172
+        // foreign keys are not supported so we just set it to an empty array
173
+        return new Table($newName, $table->getColumns(), $newIndexes, [], [], $table->getOptions());
174
+    }
175
+
176
+    /**
177
+     * @throws Exception
178
+     */
179
+    public function createSchema() {
180
+        $this->connection->getConfiguration()->setSchemaAssetsFilter(function ($asset) {
181
+            /** @var string|AbstractAsset $asset */
182
+            $filterExpression = $this->getFilterExpression();
183
+            if ($asset instanceof AbstractAsset) {
184
+                return preg_match($filterExpression, $asset->getName()) === 1;
185
+            }
186
+            return preg_match($filterExpression, $asset) === 1;
187
+        });
188
+        return $this->connection->getSchemaManager()->createSchema();
189
+    }
190
+
191
+    /**
192
+     * @param Schema $targetSchema
193
+     * @param \Doctrine\DBAL\Connection $connection
194
+     * @return \Doctrine\DBAL\Schema\SchemaDiff
195
+     */
196
+    protected function getDiff(Schema $targetSchema, \Doctrine\DBAL\Connection $connection) {
197
+        // adjust varchar columns with a length higher then getVarcharMaxLength to clob
198
+        foreach ($targetSchema->getTables() as $table) {
199
+            foreach ($table->getColumns() as $column) {
200
+                if ($column->getType() instanceof StringType) {
201
+                    if ($column->getLength() > $connection->getDatabasePlatform()->getVarcharMaxLength()) {
202
+                        $column->setType(Type::getType('text'));
203
+                        $column->setLength(null);
204
+                    }
205
+                }
206
+            }
207
+        }
208
+
209
+        $this->connection->getConfiguration()->setSchemaAssetsFilter(function ($asset) {
210
+            /** @var string|AbstractAsset $asset */
211
+            $filterExpression = $this->getFilterExpression();
212
+            if ($asset instanceof AbstractAsset) {
213
+                return preg_match($filterExpression, $asset->getName()) === 1;
214
+            }
215
+            return preg_match($filterExpression, $asset) === 1;
216
+        });
217
+        $sourceSchema = $connection->getSchemaManager()->createSchema();
218
+
219
+        // remove tables we don't know about
220
+        foreach ($sourceSchema->getTables() as $table) {
221
+            if (!$targetSchema->hasTable($table->getName())) {
222
+                $sourceSchema->dropTable($table->getName());
223
+            }
224
+        }
225
+        // remove sequences we don't know about
226
+        foreach ($sourceSchema->getSequences() as $table) {
227
+            if (!$targetSchema->hasSequence($table->getName())) {
228
+                $sourceSchema->dropSequence($table->getName());
229
+            }
230
+        }
231
+
232
+        $comparator = new Comparator();
233
+        return $comparator->compare($sourceSchema, $targetSchema);
234
+    }
235
+
236
+    /**
237
+     * @param \Doctrine\DBAL\Schema\Schema $targetSchema
238
+     * @param \Doctrine\DBAL\Connection $connection
239
+     *
240
+     * @throws Exception
241
+     */
242
+    protected function applySchema(Schema $targetSchema, \Doctrine\DBAL\Connection $connection = null) {
243
+        if (is_null($connection)) {
244
+            $connection = $this->connection;
245
+        }
246
+
247
+        $schemaDiff = $this->getDiff($targetSchema, $connection);
248
+
249
+        if (!$connection->getDatabasePlatform() instanceof MySQLPlatform) {
250
+            $connection->beginTransaction();
251
+        }
252
+        $sqls = $schemaDiff->toSql($connection->getDatabasePlatform());
253
+        $step = 0;
254
+        foreach ($sqls as $sql) {
255
+            $this->emit($sql, $step++, count($sqls));
256
+            $connection->query($sql);
257
+        }
258
+        if (!$connection->getDatabasePlatform() instanceof MySQLPlatform) {
259
+            $connection->commit();
260
+        }
261
+    }
262
+
263
+    /**
264
+     * @param string $sourceName
265
+     * @param string $targetName
266
+     */
267
+    protected function copyTable($sourceName, $targetName) {
268
+        $quotedSource = $this->connection->quoteIdentifier($sourceName);
269
+        $quotedTarget = $this->connection->quoteIdentifier($targetName);
270
+
271
+        $this->connection->exec('CREATE TABLE ' . $quotedTarget . ' (LIKE ' . $quotedSource . ')');
272
+        $this->connection->exec('INSERT INTO ' . $quotedTarget . ' SELECT * FROM ' . $quotedSource);
273
+    }
274
+
275
+    /**
276
+     * @param string $name
277
+     */
278
+    protected function dropTable($name) {
279
+        $this->connection->exec('DROP TABLE ' . $this->connection->quoteIdentifier($name));
280
+    }
281
+
282
+    /**
283
+     * @param $statement
284
+     * @return string
285
+     */
286
+    protected function convertStatementToScript($statement) {
287
+        $script = $statement . ';';
288
+        $script .= PHP_EOL;
289
+        $script .= PHP_EOL;
290
+        return $script;
291
+    }
292
+
293
+    protected function getFilterExpression() {
294
+        return '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/';
295
+    }
296
+
297
+    protected function emit($sql, $step, $max) {
298
+        if ($this->noEmit) {
299
+            return;
300
+        }
301
+        if (is_null($this->dispatcher)) {
302
+            return;
303
+        }
304
+        $this->dispatcher->dispatch('\OC\DB\Migrator::executeSql', new GenericEvent($sql, [$step + 1, $max]));
305
+    }
306
+
307
+    private function emitCheckStep($tableName, $step, $max) {
308
+        if (is_null($this->dispatcher)) {
309
+            return;
310
+        }
311
+        $this->dispatcher->dispatch('\OC\DB\Migrator::checkTable', new GenericEvent($tableName, [$step + 1, $max]));
312
+    }
313 313
 }
Please login to merge, or discard this patch.