Files
crm.clientright.ru/fix_nextcloud_collation_all.php

138 lines
4.8 KiB
PHP
Raw Permalink Normal View History

<?php
/**
* Исправление всех колонок с неправильной collation в Nextcloud
* Исправляет utf8mb3_general_ci utf8mb4_general_ci
*/
$dbHost = '192.168.128.3';
$dbUser = 'nextcloud';
$dbPass = 'nextcloud_password';
$dbName = 'nextcloud';
try {
$pdo = new PDO(
"mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4",
$dbUser,
$dbPass,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
echo "=== ИСПРАВЛЕНИЕ COLLATION В NEXTCLOUD ===\n\n";
// Находим все колонки с неправильной collation
$query = "
SELECT
TABLE_NAME,
COLUMN_NAME,
DATA_TYPE,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = ?
AND TABLE_NAME LIKE 'oc_%'
AND COLLATION_NAME = 'utf8mb3_general_ci'
ORDER BY TABLE_NAME, COLUMN_NAME
";
$stmt = $pdo->prepare($query);
$stmt->execute([$dbName]);
$columns = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($columns)) {
echo "Все колонки уже имеют правильную collation!\n";
exit(0);
}
echo "Найдено колонок с неправильной collation: " . count($columns) . "\n\n";
$fixed = 0;
$errors = 0;
foreach ($columns as $col) {
$table = $col['TABLE_NAME'];
$column = $col['COLUMN_NAME'];
$dataType = $col['DATA_TYPE'];
$charSet = $col['CHARACTER_SET_NAME'];
// Определяем новый тип данных
$newCharSet = 'utf8mb4';
$newCollation = 'utf8mb4_general_ci';
// Для TEXT типов нужно указать CHARACTER SET
$alterQuery = "ALTER TABLE `$table` MODIFY COLUMN `$column` ";
if (in_array(strtoupper($dataType), ['VARCHAR', 'CHAR', 'TEXT', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT'])) {
// Получаем текущие параметры колонки
$colInfoQuery = "SHOW FULL COLUMNS FROM `$table` WHERE Field = ?";
$colInfoStmt = $pdo->prepare($colInfoQuery);
$colInfoStmt->execute([$column]);
$colInfo = $colInfoStmt->fetch(PDO::FETCH_ASSOC);
if ($colInfo) {
$type = $colInfo['Type'];
// Заменяем charset в типе
$type = preg_replace('/utf8mb3/i', 'utf8mb4', $type);
$type = preg_replace('/utf8(_general_ci)?/i', 'utf8mb4', $type);
$null = $colInfo['Null'] === 'YES' ? 'NULL' : 'NOT NULL';
$default = $colInfo['Default'] !== null ? "DEFAULT '{$colInfo['Default']}'" : '';
$extra = $colInfo['Extra'] ?: '';
$alterQuery .= "$type CHARACTER SET $newCharSet COLLATE $newCollation $null $default $extra";
} else {
echo "⚠️ Не удалось получить информацию о колонке $table.$column\n";
continue;
}
} else {
// Для других типов просто меняем collation
$alterQuery .= "`$column` $dataType CHARACTER SET $newCharSet COLLATE $newCollation";
}
try {
echo "Исправляю: $table.$column ... ";
$pdo->exec($alterQuery);
echo "\n";
$fixed++;
} catch (PDOException $e) {
echo "❌ Ошибка: " . $e->getMessage() . "\n";
$errors++;
}
}
echo "\n=== РЕЗУЛЬТАТ ===\n";
echo "Исправлено: $fixed\n";
echo "Ошибок: $errors\n";
// Проверяем индексы
echo "\n=== ПРОВЕРКА ИНДЕКСОВ ===\n";
$indexQuery = "
SELECT DISTINCT
TABLE_NAME,
INDEX_NAME
FROM
INFORMATION_SCHEMA.STATISTICS
WHERE
TABLE_SCHEMA = ?
AND TABLE_NAME LIKE 'oc_%'
AND COLLATION = 'utf8mb3_general_ci'
";
$indexStmt = $pdo->prepare($indexQuery);
$indexStmt->execute([$dbName]);
$indexes = $indexStmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($indexes)) {
echo "⚠️ Найдено индексов с неправильной collation: " . count($indexes) . "\n";
echo "Индексы нужно пересоздать вручную или через Nextcloud\n";
} else {
echo "Все индексы имеют правильную collation\n";
}
} catch (PDOException $e) {
echo "❌ Ошибка подключения к БД: " . $e->getMessage() . "\n";
exit(1);
}