Use order by to avoid problems when chunking finds a same item again...

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2017-07-19 13:15:32 +02:00
parent 0a0dbbdf15
commit 10d7cbb71f
No known key found for this signature in database
GPG Key ID: E166FD8976B3BAC8
2 changed files with 31 additions and 10 deletions

View File

@ -28,6 +28,8 @@
namespace OC\Core\Command\Db; namespace OC\Core\Command\Db;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Table;
use OC\DB\MigrationService; use OC\DB\MigrationService;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use \OCP\IConfig; use \OCP\IConfig;
@ -271,24 +273,23 @@ class ConvertType extends Command implements CompletionAwareInterface {
/** /**
* @param Connection $fromDB * @param Connection $fromDB
* @param Connection $toDB * @param Connection $toDB
* @param $table * @param Table $table
* @param InputInterface $input * @param InputInterface $input
* @param OutputInterface $output * @param OutputInterface $output
* @suppress SqlInjectionChecker * @suppress SqlInjectionChecker
*/ */
protected function copyTable(Connection $fromDB, Connection $toDB, $table, InputInterface $input, OutputInterface $output) { protected function copyTable(Connection $fromDB, Connection $toDB, Table $table, InputInterface $input, OutputInterface $output) {
if ($table === $toDB->getPrefix() . 'migrations') { if ($table->getName() === $toDB->getPrefix() . 'migrations') {
$output->writeln('<comment>Skipping migrations table because it was already filled by running the migrations</comment>'); $output->writeln('<comment>Skipping migrations table because it was already filled by running the migrations</comment>');
return; return;
} }
$chunkSize = $input->getOption('chunk-size'); $chunkSize = $input->getOption('chunk-size');
$query = $fromDB->getQueryBuilder(); $query = $fromDB->getQueryBuilder();
$query->automaticTablePrefix(false); $query->automaticTablePrefix(false);
$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
->from($table); ->from($table->getName());
$result = $query->execute(); $result = $query->execute();
$count = $result->fetchColumn(); $count = $result->fetchColumn();
$result->closeCursor(); $result->closeCursor();
@ -306,12 +307,30 @@ class ConvertType extends Command implements CompletionAwareInterface {
$query = $fromDB->getQueryBuilder(); $query = $fromDB->getQueryBuilder();
$query->automaticTablePrefix(false); $query->automaticTablePrefix(false);
$query->select('*') $query->select('*')
->from($table) ->from($table->getName())
->setMaxResults($chunkSize); ->setMaxResults($chunkSize);
try {
$orderColumns = $table->getPrimaryKeyColumns();
} catch (DBALException $e) {
$orderColumns = [];
}
foreach ($table->getIndexes() as $index) {
if ($index->isUnique()) {
$orderColumns = array_merge($orderColumns, $index->getUnquotedColumns());
}
}
$orderColumns = array_unique($orderColumns);
if (!empty($orderColumns)) {
foreach ($orderColumns as $column) {
$query->addOrderBy($column);
}
}
$insertQuery = $toDB->getQueryBuilder(); $insertQuery = $toDB->getQueryBuilder();
$insertQuery->automaticTablePrefix(false); $insertQuery->automaticTablePrefix(false);
$insertQuery->insert($table); $insertQuery->insert($table->getName());
$parametersCreated = false; $parametersCreated = false;
for ($chunk = 0; $chunk < $numChunks; $chunk++) { for ($chunk = 0; $chunk < $numChunks; $chunk++) {
@ -329,7 +348,7 @@ class ConvertType extends Command implements CompletionAwareInterface {
} }
foreach ($row as $key => $value) { foreach ($row as $key => $value) {
$type = $this->getColumnType($table, $key); $type = $this->getColumnType($table->getName(), $key);
if ($type !== false) { if ($type !== false) {
$insertQuery->setParameter($key, $value, $type); $insertQuery->setParameter($key, $value, $type);
} else { } else {
@ -365,11 +384,13 @@ class ConvertType extends Command implements CompletionAwareInterface {
protected function convertDB(Connection $fromDB, Connection $toDB, array $tables, InputInterface $input, OutputInterface $output) { protected function convertDB(Connection $fromDB, Connection $toDB, array $tables, InputInterface $input, OutputInterface $output) {
$this->config->setSystemValue('maintenance', true); $this->config->setSystemValue('maintenance', true);
$schema = $fromDB->createSchema();
try { try {
// copy table rows // copy table rows
foreach($tables as $table) { foreach($tables as $table) {
$output->writeln($table); $output->writeln($table);
$this->copyTable($fromDB, $toDB, $table, $input, $output); $this->copyTable($fromDB, $toDB, $schema->getTable($table), $input, $output);
} }
if ($input->getArgument('type') === 'pgsql') { if ($input->getArgument('type') === 'pgsql') {
$tools = new \OC\DB\PgSqlTools($this->config); $tools = new \OC\DB\PgSqlTools($this->config);

View File

@ -34,7 +34,7 @@ class SchemaWrapper {
protected $schema; protected $schema;
/** @var array */ /** @var array */
protected $tablesToDelete; protected $tablesToDelete = [];
/** /**
* @param IDBConnection $connection * @param IDBConnection $connection