Skip oversized index alters to avoid key length 3072 errors
This commit is contained in:
parent
2419d0df7b
commit
a18bc7a0bf
|
|
@ -862,6 +862,10 @@ class Setup extends BaseController
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isIndexTooWideForInnoDb((array) $masterDef, $clientCols)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->shouldSkipUniqueIndexSync($client, $table, (array) $masterDef, $clientCols)) {
|
if ($this->shouldSkipUniqueIndexSync($client, $table, (array) $masterDef, $clientCols)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -875,6 +879,10 @@ class Setup extends BaseController
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isIndexTooWideForInnoDb((array) $masterDef, $clientCols)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->shouldSkipUniqueIndexSync($client, $table, (array) $masterDef, $clientCols)) {
|
if ($this->shouldSkipUniqueIndexSync($client, $table, (array) $masterDef, $clientCols)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1371,9 +1379,92 @@ class Setup extends BaseController
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (str_contains($messageLower, 'specified key was too long') && str_contains($messageLower, 'max key length is 3072') && str_contains($stmtLower, 'alter table')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $idxDef
|
||||||
|
* @param array<string, array<string, mixed>> $clientCols
|
||||||
|
*/
|
||||||
|
private function isIndexTooWideForInnoDb(array $idxDef, array $clientCols): bool
|
||||||
|
{
|
||||||
|
$columns = array_values(array_filter(array_map(static fn ($col) => (string) $col, (array) ($idxDef['columns'] ?? []))));
|
||||||
|
if (empty($columns)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalBytes = 0;
|
||||||
|
foreach ($columns as $column) {
|
||||||
|
$colMeta = $clientCols[$column] ?? null;
|
||||||
|
if (!is_array($colMeta)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalBytes += $this->estimateIndexedColumnBytes($colMeta);
|
||||||
|
if ($totalBytes > 3072) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $totalBytes > 3072;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $colMeta
|
||||||
|
*/
|
||||||
|
private function estimateIndexedColumnBytes(array $colMeta): int
|
||||||
|
{
|
||||||
|
$type = strtolower(trim((string) ($colMeta['Type'] ?? '')));
|
||||||
|
$collation = strtolower(trim((string) ($colMeta['Collation'] ?? '')));
|
||||||
|
|
||||||
|
$bytesPerChar = 1;
|
||||||
|
if ($collation !== '') {
|
||||||
|
if (str_starts_with($collation, 'utf32_')) {
|
||||||
|
$bytesPerChar = 4;
|
||||||
|
} elseif (str_starts_with($collation, 'utf8mb4_')) {
|
||||||
|
$bytesPerChar = 4;
|
||||||
|
} elseif (str_starts_with($collation, 'utf8mb3_') || str_starts_with($collation, 'utf8_')) {
|
||||||
|
$bytesPerChar = 3;
|
||||||
|
} elseif (str_starts_with($collation, 'ucs2_')) {
|
||||||
|
$bytesPerChar = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^(char|varchar)\((\d+)\)/i', $type, $m) === 1) {
|
||||||
|
return (int) $m[2] * $bytesPerChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^(binary|varbinary)\((\d+)\)/i', $type, $m) === 1) {
|
||||||
|
return (int) $m[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^tinytext|^text|^mediumtext|^longtext|^tinyblob|^blob|^mediumblob|^longblob/i', $type) === 1) {
|
||||||
|
return 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/^tinyint/i', $type) === 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (preg_match('/^smallint/i', $type) === 1) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (preg_match('/^mediumint/i', $type) === 1) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (preg_match('/^(int|integer)/i', $type) === 1) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
if (preg_match('/^bigint/i', $type) === 1) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $idxDef
|
* @param array<string, mixed> $idxDef
|
||||||
* @param array<string, array<string, mixed>> $clientCols
|
* @param array<string, array<string, mixed>> $clientCols
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user