diff --git a/3rdparty b/3rdparty
index 32f3284a5ca0e..caeacf211cf4c 160000
--- a/3rdparty
+++ b/3rdparty
@@ -1 +1 @@
-Subproject commit 32f3284a5ca0e372baaf458dc22aed89e257178a
+Subproject commit caeacf211cf4c264d770f2e10492528c6be9d9dd
diff --git a/core/Command/Db/Migrations/ExecuteCommand.php b/core/Command/Db/Migrations/ExecuteCommand.php
new file mode 100644
index 0000000000000..970aa9b91af59
--- /dev/null
+++ b/core/Command/Db/Migrations/ExecuteCommand.php
@@ -0,0 +1,61 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OC\Core\Command\Db\Migrations;
+
+use Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand as DBALExecuteCommand;
+use OC\DB\MigrationService;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ExecuteCommand extends DBALExecuteCommand {
+ /** @var IDBConnection */
+ private $dbConnection;
+
+ /**
+ * @param IDBConnection $connection
+ */
+ public function __construct(IDBConnection $connection) {
+ $this->dbConnection = $connection;
+
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on');
+
+ parent::configure();
+ }
+
+ public function execute(InputInterface $input,
+ OutputInterface $output) {
+ $appName = $input->getArgument('app');
+ $ms = new MigrationService();
+ $mc = $ms->buildConfiguration($appName, $this->dbConnection);
+ $this->setMigrationConfiguration($mc);
+
+ parent::execute($input, $output);
+ }
+
+}
diff --git a/core/Command/Db/Migrations/GenerateCommand.php b/core/Command/Db/Migrations/GenerateCommand.php
new file mode 100644
index 0000000000000..ba56a6ee25ab4
--- /dev/null
+++ b/core/Command/Db/Migrations/GenerateCommand.php
@@ -0,0 +1,59 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OC\Core\Command\Db\Migrations;
+
+use Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand as DBALGenerateCommand;
+use OC\DB\MigrationService;
+use OCP\IDBConnection;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class GenerateCommand extends DBALGenerateCommand {
+ /** @var IDBConnection */
+ private $dbConnection;
+
+ /**
+ * @param IDBConnection $connection
+ */
+ public function __construct(IDBConnection $connection) {
+ $this->dbConnection = $connection;
+
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on');
+
+ parent::configure();
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output) {
+ $appName = $input->getArgument('app');
+ $ms = new MigrationService();
+ $mc = $ms->buildConfiguration($appName, $this->dbConnection);
+ $this->setMigrationConfiguration($mc);
+
+ parent::execute($input, $output);
+ }
+
+}
diff --git a/core/Command/Db/Migrations/MigrateCommand.php b/core/Command/Db/Migrations/MigrateCommand.php
new file mode 100644
index 0000000000000..73966515f7476
--- /dev/null
+++ b/core/Command/Db/Migrations/MigrateCommand.php
@@ -0,0 +1,59 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OC\Core\Command\Db\Migrations;
+
+use Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand as DBALMigrateCommand;
+use OC\DB\MigrationService;
+use OCP\IDBConnection;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class MigrateCommand extends DBALMigrateCommand {
+ /** @var IDBConnection */
+ private $dbConnection;
+
+ /**
+ * @param IDBConnection $connection
+ */
+ public function __construct(IDBConnection $connection) {
+ $this->dbConnection = $connection;
+
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on');
+
+ parent::configure();
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output) {
+ $appName = $input->getArgument('app');
+ $ms = new MigrationService();
+ $mc = $ms->buildConfiguration($appName, $this->dbConnection);
+ $this->setMigrationConfiguration($mc);
+
+ parent::execute($input, $output);
+ }
+
+}
diff --git a/core/Command/Db/Migrations/StatusCommand.php b/core/Command/Db/Migrations/StatusCommand.php
new file mode 100644
index 0000000000000..fceae2af7bc59
--- /dev/null
+++ b/core/Command/Db/Migrations/StatusCommand.php
@@ -0,0 +1,60 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OC\Core\Command\Db\Migrations;
+
+use Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand as DBALStatusCommand;
+use OC\DB\MigrationService;
+use OCP\IDBConnection;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class StatusCommand extends DBALStatusCommand {
+
+ /** @var IDBConnection */
+ private $dbConnection;
+
+ /**
+ * @param IDBConnection $connection
+ */
+ public function __construct(IDBConnection $connection) {
+ $this->dbConnection = $connection;
+
+ parent::__construct();
+ }
+
+ protected function configure() {
+ parent::configure();
+
+ $this->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on');
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output) {
+ $appName = $input->getArgument('app');
+ $ms = new MigrationService();
+ $mc = $ms->buildConfiguration($appName, $this->dbConnection);
+ $this->setMigrationConfiguration($mc);
+
+ parent::execute($input, $output);
+ }
+
+}
diff --git a/core/register_command.php b/core/register_command.php
index 6f31adafe926f..a99b7d7327045 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -84,6 +84,10 @@
$application->add(new OC\Core\Command\Db\GenerateChangeScript());
$application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory(\OC::$server->getConfig())));
+ $application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->getDatabaseConnection()));
+ $application->add(new OC\Core\Command\Db\Migrations\MigrateCommand(\OC::$server->getDatabaseConnection()));
+ $application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->getDatabaseConnection()));
+ $application->add(new OC\Core\Command\Db\Migrations\ExecuteCommand(\OC::$server->getDatabaseConnection()));
$application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Encryption\Enable(\OC::$server->getConfig(), \OC::$server->getEncryptionManager()));
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 7a4cc6eaa8461..529934b7c6dec 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -374,6 +374,10 @@
'OC\\Core\\Command\\Config\\System\\SetConfig' => $baseDir . '/core/Command/Config/System/SetConfig.php',
'OC\\Core\\Command\\Db\\ConvertType' => $baseDir . '/core/Command/Db/ConvertType.php',
'OC\\Core\\Command\\Db\\GenerateChangeScript' => $baseDir . '/core/Command/Db/GenerateChangeScript.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\ExecuteCommand' => $baseDir . '/core/Command/Db/Migrations/ExecuteCommand.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\GenerateCommand' => $baseDir . '/core/Command/Db/Migrations/GenerateCommand.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\MigrateCommand' => $baseDir . '/core/Command/Db/Migrations/MigrateCommand.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\StatusCommand' => $baseDir . '/core/Command/Db/Migrations/StatusCommand.php',
'OC\\Core\\Command\\Encryption\\ChangeKeyStorageRoot' => $baseDir . '/core/Command/Encryption/ChangeKeyStorageRoot.php',
'OC\\Core\\Command\\Encryption\\DecryptAll' => $baseDir . '/core/Command/Encryption/DecryptAll.php',
'OC\\Core\\Command\\Encryption\\Disable' => $baseDir . '/core/Command/Encryption/Disable.php',
@@ -439,7 +443,9 @@
'OC\\DB\\MDB2SchemaManager' => $baseDir . '/lib/private/DB/MDB2SchemaManager.php',
'OC\\DB\\MDB2SchemaReader' => $baseDir . '/lib/private/DB/MDB2SchemaReader.php',
'OC\\DB\\MDB2SchemaWriter' => $baseDir . '/lib/private/DB/MDB2SchemaWriter.php',
+ 'OC\\DB\\MigrationConfiguration' => $baseDir . '/lib/private/DB/MigrationConfiguration.php',
'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php',
+ 'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php',
'OC\\DB\\MySQLMigrator' => $baseDir . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\NoCheckMigrator' => $baseDir . '/lib/private/DB/NoCheckMigrator.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 6a063f0d8c790..66d9aa1ecf38c 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -404,6 +404,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Command\\Config\\System\\SetConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/SetConfig.php',
'OC\\Core\\Command\\Db\\ConvertType' => __DIR__ . '/../../..' . '/core/Command/Db/ConvertType.php',
'OC\\Core\\Command\\Db\\GenerateChangeScript' => __DIR__ . '/../../..' . '/core/Command/Db/GenerateChangeScript.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\ExecuteCommand' => __DIR__ . '/../../..' . '/core/Command/Db/Migrations/ExecuteCommand.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\GenerateCommand' => __DIR__ . '/../../..' . '/core/Command/Db/Migrations/GenerateCommand.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\MigrateCommand' => __DIR__ . '/../../..' . '/core/Command/Db/Migrations/MigrateCommand.php',
+ 'OC\\Core\\Command\\Db\\Migrations\\StatusCommand' => __DIR__ . '/../../..' . '/core/Command/Db/Migrations/StatusCommand.php',
'OC\\Core\\Command\\Encryption\\ChangeKeyStorageRoot' => __DIR__ . '/../../..' . '/core/Command/Encryption/ChangeKeyStorageRoot.php',
'OC\\Core\\Command\\Encryption\\DecryptAll' => __DIR__ . '/../../..' . '/core/Command/Encryption/DecryptAll.php',
'OC\\Core\\Command\\Encryption\\Disable' => __DIR__ . '/../../..' . '/core/Command/Encryption/Disable.php',
@@ -469,7 +473,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\DB\\MDB2SchemaManager' => __DIR__ . '/../../..' . '/lib/private/DB/MDB2SchemaManager.php',
'OC\\DB\\MDB2SchemaReader' => __DIR__ . '/../../..' . '/lib/private/DB/MDB2SchemaReader.php',
'OC\\DB\\MDB2SchemaWriter' => __DIR__ . '/../../..' . '/lib/private/DB/MDB2SchemaWriter.php',
+ 'OC\\DB\\MigrationConfiguration' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationConfiguration.php',
'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php',
+ 'OC\\DB\\MigrationService' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php',
'OC\\DB\\MySQLMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\NoCheckMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/NoCheckMigrator.php',
diff --git a/lib/private/DB/MDB2SchemaReader.php b/lib/private/DB/MDB2SchemaReader.php
index c198bb31e0011..205fe79f2b7d9 100644
--- a/lib/private/DB/MDB2SchemaReader.php
+++ b/lib/private/DB/MDB2SchemaReader.php
@@ -80,8 +80,10 @@ public function __construct(IConfig $config, AbstractPlatform $platform) {
* @return \Doctrine\DBAL\Schema\Schema
* @throws \DomainException
*/
- public function loadSchemaFromFile($file) {
- $schema = new \Doctrine\DBAL\Schema\Schema();
+ public function loadSchemaFromFile($file, $schema = null) {
+ if (is_null($schema)) {
+ $schema = new \Doctrine\DBAL\Schema\Schema();
+ }
$loadEntities = libxml_disable_entity_loader(false);
$xml = simplexml_load_file($file);
libxml_disable_entity_loader($loadEntities);
diff --git a/lib/private/DB/MigrationConfiguration.php b/lib/private/DB/MigrationConfiguration.php
new file mode 100644
index 0000000000000..cc8b592064f76
--- /dev/null
+++ b/lib/private/DB/MigrationConfiguration.php
@@ -0,0 +1,52 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+namespace OC\DB;
+
+use Doctrine\DBAL\Migrations\Finder\MigrationFinderInterface;
+use Doctrine\DBAL\Migrations\OutputWriter;
+use Doctrine\DBAL\Platforms\OraclePlatform;
+
+class MigrationConfiguration extends \Doctrine\DBAL\Migrations\Configuration\Configuration {
+
+ function __construct(Connection $connection, OutputWriter $outputWriter = null, MigrationFinderInterface $finder = null) {
+ parent::__construct($connection, $outputWriter, $finder);
+
+ $this->setMigrationsTableName($this->getMigrationsTableName());
+ $this->setMigrationsColumnName($this->getMigrationsColumnName());
+ }
+
+ public function setMigrationsColumnName($columnName) {
+ $platform = $this->getConnection()->getDatabasePlatform();
+ if ($platform instanceof OraclePlatform) {
+ $columnName = $platform->quoteIdentifier($columnName);
+ }
+ parent::setMigrationsColumnName($columnName);
+ }
+
+ public function setMigrationsTableName($tableName) {
+ $platform = $this->getConnection()->getDatabasePlatform();
+ if ($platform instanceof OraclePlatform) {
+ $tableName = $platform->quoteIdentifier($tableName);
+ }
+ parent::setMigrationsTableName($tableName);
+ }
+
+}
diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php
new file mode 100644
index 0000000000000..87a64f192e33f
--- /dev/null
+++ b/lib/private/DB/MigrationService.php
@@ -0,0 +1,76 @@
+
+ *
+ * @copyright Copyright (c) 2016, ownCloud GmbH.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OC\DB;
+
+use Doctrine\DBAL\Migrations\Configuration\Configuration;
+use Doctrine\DBAL\Migrations\Migration;
+use Doctrine\DBAL\Migrations\OutputWriter;
+use OCP\IDBConnection;
+
+class MigrationService {
+
+ /**
+ * @param string $appName
+ * @param IDBConnection $connection
+ * @return MigrationConfiguration
+ * @throws \Exception
+ */
+ public function buildConfiguration($appName, IDBConnection $connection) {
+ if ($appName === 'core') {
+ $migrationsPath = \OC::$SERVERROOT . '/core/Migrations';
+ $migrationsNamespace = 'OC\\Migrations';
+ } else {
+ $appPath = \OC_App::getAppPath($appName);
+ if (!$appPath) {
+ throw new \InvalidArgumentException('Path to app is not defined.');
+ }
+ $migrationsPath = "$appPath/appinfo/Migrations";
+ $migrationsNamespace = "OCA\\$appName\\Migrations";
+ }
+
+ if (!is_dir($migrationsPath)) {
+ if (!mkdir($migrationsPath)) {
+ throw new \Exception("Could not create migration folder \"$migrationsPath\"");
+ };
+ }
+ $prefix = $connection->getPrefix();
+ $mc = new MigrationConfiguration($connection);
+ $mc->setMigrationsDirectory($migrationsPath);
+ $mc->setMigrationsNamespace($migrationsNamespace);
+ $mc->setMigrationsTableName("{$prefix}{$appName}_migration_versions");
+ return $mc;
+ }
+
+ /**
+ * @param Configuration $migrationConfiguration
+ * @param bool $noMigrationException
+ */
+ public function migrate($migrationConfiguration, $noMigrationException = false) {
+ $migrationConfiguration->setOutputWriter(new OutputWriter(function ($message){
+ \OCP\Util::writeLog('migrations', $message, \OCP\Util::INFO);
+ }));
+
+ $migration = new Migration($migrationConfiguration);
+ $migration->setNoMigrationException($noMigrationException);
+ $migration->migrate();
+ }
+}
diff --git a/lib/private/DB/OracleConnection.php b/lib/private/DB/OracleConnection.php
index 08d713651722a..106f219d1a9ba 100644
--- a/lib/private/DB/OracleConnection.php
+++ b/lib/private/DB/OracleConnection.php
@@ -30,9 +30,14 @@ class OracleConnection extends Connection {
* Quote the keys of the array
*/
private function quoteKeys(array $data) {
- $return = array();
+ $return = [];
+ $c = $this->getDatabasePlatform()->getIdentifierQuoteCharacter();
foreach($data as $key => $value) {
- $return[$this->quoteIdentifier($key)] = $value;
+ if ($key[0] !== $c) {
+ $return[$this->quoteIdentifier($key)] = $value;
+ } else {
+ $return[$key] = $value;
+ }
}
return $return;
}
@@ -40,8 +45,10 @@ private function quoteKeys(array $data) {
/**
* {@inheritDoc}
*/
- public function insert($tableName, array $data, array $types = array()) {
- $tableName = $this->quoteIdentifier($tableName);
+ public function insert($tableName, array $data, array $types = []) {
+ if ($tableName[0] !== $this->getDatabasePlatform()->getIdentifierQuoteCharacter()) {
+ $tableName = $this->quoteIdentifier($tableName);
+ }
$data = $this->quoteKeys($data);
return parent::insert($tableName, $data, $types);
}
@@ -49,8 +56,10 @@ public function insert($tableName, array $data, array $types = array()) {
/**
* {@inheritDoc}
*/
- public function update($tableName, array $data, array $identifier, array $types = array()) {
- $tableName = $this->quoteIdentifier($tableName);
+ public function update($tableName, array $data, array $identifier, array $types = []) {
+ if ($tableName[0] !== $this->getDatabasePlatform()->getIdentifierQuoteCharacter()) {
+ $tableName = $this->quoteIdentifier($tableName);
+ }
$data = $this->quoteKeys($data);
$identifier = $this->quoteKeys($identifier);
return parent::update($tableName, $data, $identifier, $types);
@@ -59,10 +68,12 @@ public function update($tableName, array $data, array $identifier, array $types
/**
* {@inheritDoc}
*/
- public function delete($tableExpression, array $identifier, array $types = array()) {
- $tableName = $this->quoteIdentifier($tableExpression);
+ public function delete($tableExpression, array $identifier, array $types = []) {
+ if ($tableExpression[0] !== $this->getDatabasePlatform()->getIdentifierQuoteCharacter()) {
+ $tableExpression = $this->quoteIdentifier($tableExpression);
+ }
$identifier = $this->quoteKeys($identifier);
- return parent::delete($tableName, $identifier);
+ return parent::delete($tableExpression, $identifier);
}
/**
diff --git a/lib/private/Installer.php b/lib/private/Installer.php
index 38d0ce1368473..3073b8ce64126 100644
--- a/lib/private/Installer.php
+++ b/lib/private/Installer.php
@@ -102,11 +102,17 @@ public function installApp($appId) {
$info = OC_App::getAppInfo($basedir.'/appinfo/info.xml', true);
//install the database
- if(is_file($basedir.'/appinfo/database.xml')) {
- if (\OC::$server->getAppConfig()->getValue($info['id'], 'installed_version') === null) {
- OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
- } else {
- OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml');
+ if (isset($appData['use-migrations']) && $appData['use-migrations'] === 'true') {
+ $ms = new \OC\DB\MigrationService();
+ $mc = $ms->buildConfiguration($appId, \OC::$server->getDatabaseConnection());
+ $ms->migrate($mc);
+ } else {
+ if(is_file($basedir.'/appinfo/database.xml')) {
+ if (\OC::$server->getAppConfig()->getValue($info['id'], 'installed_version') === null) {
+ OC_DB::createDbFromStructure($basedir . '/appinfo/database.xml');
+ } else {
+ OC_DB::updateDbFromStructure($basedir . '/appinfo/database.xml');
+ }
}
}
@@ -472,17 +478,23 @@ public static function installShippedApps($softErrors = false) {
* @return integer
*/
public static function installShippedApp($app) {
+
+ $info = OC_App::getAppInfo($app);
+ if (is_null($info)) {
+ return false;
+ }
+
//install the database
$appPath = OC_App::getAppPath($app);
- if(is_file("$appPath/appinfo/database.xml")) {
- try {
- OC_DB::createDbFromStructure("$appPath/appinfo/database.xml");
- } catch (TableExistsException $e) {
- throw new HintException(
- 'Failed to enable app ' . $app,
- 'Please ask for help via one of our support channels.',
- 0, $e
- );
+ if (isset($info['use-migrations']) && $info['use-migrations'] === 'true') {
+ $ms = new \OC\DB\MigrationService();
+ $mc = $ms->buildConfiguration($app, \OC::$server->getDatabaseConnection());
+ $ms->migrate($mc);
+ } else {
+ if (\OC::$server->getAppConfig()->getValue($info['id'], 'installed_version') === null) {
+ if (is_file($appPath . '/appinfo/database.xml')) {
+ OC_DB::createDbFromStructure($appPath . '/appinfo/database.xml');
+ }
}
}
@@ -490,10 +502,6 @@ public static function installShippedApp($app) {
\OC_App::registerAutoloading($app, $appPath);
self::includeAppScript("$appPath/appinfo/install.php");
- $info = OC_App::getAppInfo($app);
- if (is_null($info)) {
- return false;
- }
\OC_App::setupBackgroundJobs($info['background-jobs']);
OC_App::executeRepairSteps($app, $info['repair-steps']['install']);
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index 81a5343fe2103..944f3a01a9eeb 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -330,6 +330,8 @@ public function install($options) {
try {
$dbSetup->initialize($options);
$dbSetup->setupDatabase($username);
+ // apply necessary migrations
+ $dbSetup->runMigrations();
} catch (\OC\DatabaseSetupException $e) {
$error[] = array(
'error' => $e->getMessage(),
diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php
index dbf46888ffe3c..cae46efd33932 100644
--- a/lib/private/Setup/AbstractDatabase.php
+++ b/lib/private/Setup/AbstractDatabase.php
@@ -28,6 +28,7 @@
use OC\AllConfig;
use OC\DB\ConnectionFactory;
+use OC\DB\MigrationService;
use OCP\IConfig;
use OCP\IL10N;
use OCP\ILogger;
@@ -144,4 +145,13 @@ protected function connect(array $configOverwrite = []) {
* @param string $userName
*/
abstract public function setupDatabase($userName);
+
+ public function runMigrations() {
+ if (!is_dir(\OC::$SERVERROOT."/core/Migrations")) {
+ return;
+ }
+ $ms = new MigrationService();
+ $mc = $ms->buildConfiguration('core', \OC::$server->getDatabaseConnection());
+ $ms->migrate($mc, true);
+ }
}
diff --git a/lib/private/Updater.php b/lib/private/Updater.php
index a66d49941cd88..46471f0acfca6 100644
--- a/lib/private/Updater.php
+++ b/lib/private/Updater.php
@@ -284,8 +284,13 @@ private function doUpgrade($currentVersion, $installedVersion) {
protected function doCoreUpgrade() {
$this->emit('\OC\Updater', 'dbUpgradeBefore');
- // do the real upgrade
- \OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml');
+ // execute core migrations
+ if (is_dir(\OC::$SERVERROOT."/core/Migrations")) {
+ $ms = new \OC\DB\MigrationService();
+ $mc = $ms->buildConfiguration('core', \OC::$server->getDatabaseConnection());
+
+ $ms->migrate($mc, true);
+ }
$this->emit('\OC\Updater', 'dbUpgrade');
}
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index adf29601ac6d1..169fe96bcf54c 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -1122,8 +1122,14 @@ public static function updateApp($appId) {
}
$appData = self::getAppInfo($appId);
self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
- if (file_exists($appPath . '/appinfo/database.xml')) {
- OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
+ if (isset($appData['use-migrations']) && $appData['use-migrations'] === 'true') {
+ $ms = new \OC\DB\MigrationService();
+ $mc = $ms->buildConfiguration($appId, \OC::$server->getDatabaseConnection());
+ $ms->migrate($mc, true);
+ } else {
+ if (file_exists($appPath . '/appinfo/database.xml')) {
+ OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
+ }
}
self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
diff --git a/tests/lib/DB/MigrationsTest.php b/tests/lib/DB/MigrationsTest.php
new file mode 100644
index 0000000000000..0ac82af0a801b
--- /dev/null
+++ b/tests/lib/DB/MigrationsTest.php
@@ -0,0 +1,29 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+
+namespace Test\DB;
+
+use OC\DB\MigrationService;
+
+/**
+ * Class MigrationsTest
+ *
+ * @group DB
+ *
+ * @package Test\DB
+ */
+class MigrationsTest extends \Test\TestCase {
+ public function testMigrationTableCreation() {
+ $m = new MigrationService();
+ $appName = 'testing';
+ $conf = $m->buildConfiguration($appName, \OC::$server->getDatabaseConnection());
+ $this->assertTrue($conf->createMigrationTable());
+ $this->assertFalse($conf->createMigrationTable());
+ }
+}