diff options
-rw-r--r-- | core/command/db/convertfromsqlite.php | 164 | ||||
-rw-r--r-- | core/register_command.php | 1 |
2 files changed, 165 insertions, 0 deletions
diff --git a/core/command/db/convertfromsqlite.php b/core/command/db/convertfromsqlite.php new file mode 100644 index 00000000000..85cf1e38c18 --- /dev/null +++ b/core/command/db/convertfromsqlite.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ + +namespace OC\Core\Command\Db; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ConvertFromSqlite extends Command { + protected function configure() { + $this + ->setName('db:convert-from-sqlite') + ->setDescription('Convert the owncloud sqlite database to the newly configured one') + ->addArgument( + 'type', + InputArgument::REQUIRED, + 'the type of the database to convert to' + ) + ->addArgument( + 'username', + InputArgument::REQUIRED, + 'the username of the database to convert to' + ) + ->addArgument( + 'hostname', + InputArgument::REQUIRED, + 'the hostname of the database to convert to' + ) + ->addArgument( + 'database', + InputArgument::REQUIRED, + 'the name of the database to convert to' + ) + ->addOption( + 'port', + null, + InputOption::VALUE_REQUIRED, + 'the port of the database to convert to' + ) + ->addOption( + 'password', + null, + InputOption::VALUE_REQUIRED, + 'the password of the database to convert to. Will be asked when not specified' + ) + ; + } + + private static $type2driver = array( + 'mysql' => 'pdo_mysql', + 'pgsql' => 'pdo_pgsql', + 'oci' => 'oci8', + 'mssql' => 'pdo_sqlsrv', + ); + protected function execute(InputInterface $input, OutputInterface $output) { + // connect 'from' database + $datadir = \OC_Config::getValue( "datadirectory", \OC::$SERVERROOT.'/data' ); + $name = \OC_Config::getValue( "dbname", "owncloud" ); + $dbfile = $datadir.'/'.$name.'.db'; + $connectionParams = array( + 'path' => $dbfile, + 'driver' => 'pdo_sqlite', + ); + $fromDB = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); + + // connect 'to' database + $type = $input->getArgument('type'); + $username = $input->getArgument('username'); + $hostname = $input->getArgument('hostname'); + $dbname = $input->getArgument('database'); + + if ($input->getOption('password')) { + $password = $input->getOption('password'); + } else { + // TODO: should be moved to the interact function + $dialog = $this->getHelperSet()->get('dialog'); + $password = $dialog->askHiddenResponse( + $output, + 'What is the database password?', + false + ); + } + $connectionParams = array( + 'driver' => self::$type2driver[$type], + 'user' => $username, + 'password' => $password, + 'host' => $hostname, + 'dbname' => $dbname, + ); + if ($input->getOption('port')) { + $connectionParams['port'] = $input->getOption('port'); + } + $toDB = \Doctrine\DBAL\DriverManager::getConnection($connectionParams); + + // create tables in new database + $schemaManager = new \OC\DB\MDB2SchemaManager($toDB); + $schemaManager->createDbFromStructure(\OC::$SERVERROOT.'/db_structure.xml'); + $apps = \OC_App::getEnabledApps(); + foreach($apps as $app) { + if(file_exists(\OC_App::getAppPath($app).'/appinfo/database.xml')) { + $schemaManager->createDbFromStructure(\OC_App::getAppPath($app).'/appinfo/database.xml'); + } + } + + // get tables from 'to' database + $toTables = $this->getTables($toDB); + // get tables from 'from' database + $fromTables = $this->getTables($fromDB); + // warn/fail if there are more tables in 'from' database + $tables = array_diff($fromTables, $toTables); + if (!empty($tables)) { + $output->writeln('<error>The following tables do NOT exist any more: '.join(', ', $tables).'</error>'); + $dialog = $this->getHelperSet()->get('dialog'); + if (!$dialog->askConfirmation( + $output, + '<question>Continue with the convertion?</question>', + false + )) { + return; + } + } + // copy table rows + $tables = array_intersect($toTables, $fromTables); + foreach($tables as $table) { + $output->writeln($table); + $this->copyTable($fromDB, $toDB, $table, $output); + } + } + + private function getTables($db) { + $schemaManager = $db->getSchemaManager(); + return $schemaManager->listTableNames(); + } + + private function copyTable($fromDB, $toDB, $table, $output) { + $progress = $this->getHelperSet()->get('progress'); + $query = 'SELECT COUNT(*) from '.$table; + $count = $fromDB->fetchColumn($query); + $query = 'SELECT * from '.$table; + $statement = $fromDB->executeQuery($query); + $query = 'DELETE FROM '.$table; + $toDB->executeUpdate($query); + $progress->start($output, $count); + if ($count > 100) { + $progress->setRedrawFrequency(5); + } else { + $progress->setRedrawFrequency(1); + } + while($row = $statement->fetch()) { + $progress->advance(); + $toDB->insert($table, $row); + } + $progress->finish(); + } +}
\ No newline at end of file diff --git a/core/register_command.php b/core/register_command.php index e4f3b124365..419747ebb44 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -9,6 +9,7 @@ /** @var $application Symfony\Component\Console\Application */ $application->add(new OC\Core\Command\Status); $application->add(new OC\Core\Command\Db\GenerateChangeScript()); +$application->add(new OC\Core\Command\Db\ConvertFromSqlite()); $application->add(new OC\Core\Command\Upgrade()); $application->add(new OC\Core\Command\Maintenance\SingleUser()); $application->add(new OC\Core\Command\App\Disable()); |