Skip to content

Commit b3e926f

Browse files
authored
Merge pull request #4710 from nextcloud/fix/pgsql-index-creation
Catch IndexAlreadyExists
2 parents 9f6773e + b935fe3 commit b3e926f

1 file changed

Lines changed: 33 additions & 7 deletions

File tree

lib/Db/V10/IndexManager.php

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace OCA\Polls\Db\V10;
1010

11+
use Doctrine\DBAL\Schema\Exception\IndexAlreadyExists;
1112
use Doctrine\DBAL\Schema\Exception\IndexDoesNotExist;
1213
use Exception;
1314
use OCA\Polls\Migration\V10\TableSchema;
@@ -359,7 +360,7 @@ public function createIndex(string $tableName, string $indexName, array $columns
359360

360361
// Check by name: if a named index already exists, verify its columns
361362
if ($hasName && $table->hasIndex($indexName)) {
362-
if ($this->columnsMatch($table->getIndex($indexName)->getColumns(), $columns)) {
363+
if ($this->columnsMatch($table->getIndex($indexName)->getUnquotedColumns(), $columns)) {
363364
// Named index with same columns already exists, skip creation and return success message
364365
return ucfirst($type) . ' ' . $indexName . ' with correct configuration already exists in ' . $tableName . '. Skip creation.';
365366
}
@@ -370,7 +371,7 @@ public function createIndex(string $tableName, string $indexName, array $columns
370371

371372
// Check by columns: look further for any existing index with same uniqueness and same columns
372373
foreach ($table->getIndexes() as $index) {
373-
if ($index->isUnique() === $unique && $this->columnsMatch($index->getColumns(), $columns)) {
374+
if ($index->isUnique() === $unique && $this->columnsMatch($index->getUnquotedColumns(), $columns)) {
374375
if (!$hasName) {
375376
// If index is unnamed and index with matching configuraton is found, skip creation and return success message
376377
return ucfirst($type) . ' for ' . json_encode($columns) . ' already exists as ' . $index->getName() . ' in ' . $tableName;
@@ -382,11 +383,36 @@ public function createIndex(string $tableName, string $indexName, array $columns
382383
}
383384
}
384385

385-
// now create the new index, either, because it did not exist at all, or because the existing one(s) were dropped due to mismatch
386-
if ($unique) {
387-
$table->addUniqueIndex($columns, $hasName ? $indexName : null);
388-
} else {
389-
$table->addIndex($columns, $hasName ? $indexName : null);
386+
// now create the new index, either, because it did not exist at all, or
387+
// because the existing one(s) were dropped due to mismatch
388+
try {
389+
if ($unique) {
390+
$table->addUniqueIndex($columns, $hasName ? $indexName : null);
391+
} else {
392+
$table->addIndex($columns, $hasName ? $indexName : null);
393+
}
394+
} catch (IndexAlreadyExists) {
395+
// Catch Exception and treat the index as existing
396+
// Especially catches pgsql error in situations, where the prior
397+
// check did not detect the existing index
398+
399+
// Let's add some details about the existing indices to the log
400+
// collect expected and actual index configurations
401+
$indexDump = [];
402+
foreach ($table->getIndexes() as $idx) {
403+
$indexDump[] = $idx->getName() . '[' . implode(',', $idx->getColumns()) . ']' . ($idx->isUnique() ? ' UNIQUE' : '');
404+
}
405+
406+
// Log the exception with details about the existing indices as a warning log entry
407+
$this->logger->warning(
408+
'IndexAlreadyExists caught for {table}: expected columns {expected}, existing indices: {indices}',
409+
[
410+
'table' => $prefixedTable,
411+
'expected' => json_encode($columns),
412+
'indices' => implode(' | ', $indexDump),
413+
]
414+
);
415+
return ucfirst($type) . ' for ' . json_encode($columns) . ' already exists in ' . $tableName . ' (detected via exception). Skip creation.';
390416
}
391417
$message[] = 'Added ' . $type . ' ' . ($hasName ? $indexName : '(auto)') . ' for ' . json_encode($columns) . ' to ' . $tableName;
392418

0 commit comments

Comments
 (0)