Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Improvement] Prevent db errors on index updates on classes rebuild #16871

Merged
merged 7 commits into from May 3, 2024
47 changes: 33 additions & 14 deletions models/DataObject/ClassDefinition/Helper/Dao.php
Expand Up @@ -15,8 +15,6 @@

namespace Pimcore\Model\DataObject\ClassDefinition\Helper;

use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Pimcore\Db\Helper;
use Pimcore\Model\DataObject;

/**
Expand Down Expand Up @@ -52,9 +50,9 @@ protected function addIndexToField(DataObject\ClassDefinition\Data $field, strin
$columnName .= ',`fieldname`';
}
}
Helper::queryIgnoreError($this->db, 'ALTER TABLE `'.$table.'` ADD ' . $uniqueStr . 'INDEX `' . $prefix . $indexName.'` ('.$columnName.');',
[UniqueConstraintViolationException::class]
);
if ($this->indexDoesNotExist($table, $prefix, $indexName)) {
$this->db->executeQuery('ALTER TABLE `' . $table . '` ADD ' . $uniqueStr . 'INDEX `' . $prefix . $indexName . '` (' . $columnName . ');');
}
}
} else {
// single -column field
Expand All @@ -67,21 +65,25 @@ protected function addIndexToField(DataObject\ClassDefinition\Data $field, strin
$columnName .= ',`fieldname`';
}
}
Helper::queryIgnoreError($this->db, 'ALTER TABLE `'.$table.'` ADD ' . $uniqueStr . 'INDEX `' . $prefix . $indexName.'` ('.$columnName.');',
[UniqueConstraintViolationException::class]
);
if ($this->indexDoesNotExist($table, $prefix, $indexName)) {
$this->db->executeQuery('ALTER TABLE `' . $table . '` ADD ' . $uniqueStr . 'INDEX `' . $prefix . $indexName . '` (' . $columnName . ');');
}
}
} else {
if (is_array($columnType)) {
// multicolumn field
foreach ($columnType as $fkey => $fvalue) {
$columnName = $field->getName().'__'.$fkey;
Helper::queryIgnoreError($this->db, 'ALTER TABLE `'.$table.'` DROP INDEX `'. $prefix . $columnName.'`;');
$indexName = $field->getName().'__'.$fkey;
if ($this->indexExists($table, $prefix, $indexName)) {
$this->db->executeQuery('ALTER TABLE `' . $table . '` DROP INDEX `' . $prefix . $indexName . '`;');
}
}
} else {
// single -column field
$columnName = $field->getName();
Helper::queryIgnoreError($this->db, 'ALTER TABLE `'.$table.'` DROP INDEX `'. $prefix . $columnName.'`;');
$indexName = $field->getName();
if ($this->indexExists($table, $prefix, $indexName)) {
$this->db->executeQuery('ALTER TABLE `' . $table . '` DROP INDEX `' . $prefix . $indexName . '`;');
}
}
}
}
Expand Down Expand Up @@ -172,11 +174,28 @@ protected function removeIndices(string $table, array $columnsToRemove, array $p
if ($columnsToRemove) {
$lowerCaseColumns = array_map('strtolower', $protectedColumns);
foreach ($columnsToRemove as $value) {
if (!in_array(strtolower($value), $lowerCaseColumns)) {
Helper::queryIgnoreError($this->db, 'ALTER TABLE `'.$table.'` DROP INDEX `u_index_'. $value . '`;');
if (!in_array(strtolower($value), $lowerCaseColumns) && $this->indexExists($table, 'u_index_', $value)) {
$this->db->executeQuery('ALTER TABLE `'.$table.'` DROP INDEX `u_index_'. $value . '`;');
}
}
$this->resetValidTableColumnsCache($table);
}
}

/**
* For MariaDB, it would be possible to use 'ADD/DROP INDEX IF EXISTS' but this is not supported by MySQL
*/
protected function indexExists(string $table, string $prefix, mixed $indexName): bool
{
$exist = $this->db->fetchFirstColumn(
"SELECT COUNT(*) FROM information_schema.statistics WHERE table_name = '${table}' AND index_name = '${prefix}${indexName}' AND table_schema = DATABASE();"
);

return (\count($exist) > 0) && (1 === $exist[0]);
}

protected function indexDoesNotExist(string $table, string $prefix, mixed $indexName): bool
{
return !$this->indexExists($table, $prefix, $indexName);
}
}