add csv analysis option
This commit is contained in:
@@ -427,6 +427,9 @@ public function insertMultipleRows(string $schema, string $table, array $rows, a
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Форматирует ошибку импорта с детальной информацией
|
||||
*/
|
||||
/**
|
||||
* Форматирует ошибку импорта с детальной информацией
|
||||
*/
|
||||
@@ -444,10 +447,9 @@ private function formatImportError(\PDOException $e, int $lineNumber, array $row
|
||||
$value = $rowData[$field] ?? 'N/A';
|
||||
$columnType = $columnTypes[$field]['type'] ?? 'unknown';
|
||||
|
||||
// Проверяем, не слишком ли большое число
|
||||
if (is_numeric($value)) {
|
||||
$valueLength = strlen((string)$value);
|
||||
return $baseMsg . "Поле '{$field}' ({$columnType}): значение '{$value}' (длина: {$valueLength}) слишком большое или имеет неверный формат. " .
|
||||
return $baseMsg . "Поле '{$field}' ({$columnType}): значение '{$value}' (длина: {$valueLength}) слишком большое. " .
|
||||
"Данные строки: " . $this->formatRowData($rowData);
|
||||
}
|
||||
|
||||
@@ -457,15 +459,44 @@ private function formatImportError(\PDOException $e, int $lineNumber, array $row
|
||||
return $baseMsg . "Данные обрезаны. Строка: " . $this->formatRowData($rowData);
|
||||
}
|
||||
|
||||
// Foreign Key constraint
|
||||
// ✅ Foreign Key constraint - УЛУЧШЕННАЯ ДИАГНОСТИКА
|
||||
if ($code === '23000' && str_contains($message, 'foreign key constraint')) {
|
||||
// Пытаемся извлечь имя FK constraint
|
||||
if (preg_match('/CONSTRAINT `([^`]+)`/', $message, $matches)) {
|
||||
$constraintName = $matches[1];
|
||||
|
||||
// Из имени constraint часто можно понять поле (например: fk_table_field)
|
||||
// Пробуем найти поле в rowData которое может быть причиной
|
||||
$suspectFields = [];
|
||||
foreach ($rowData as $fieldName => $fieldValue) {
|
||||
if ($fieldValue !== null && $fieldValue !== '') {
|
||||
// Если имя constraint содержит имя поля
|
||||
if (stripos($constraintName, $fieldName) !== false) {
|
||||
$suspectFields[] = "{$fieldName}='{$fieldValue}'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($suspectFields)) {
|
||||
return $baseMsg . "❌ СВЯЗАННОЕ ЗНАЧЕНИЕ НЕ НАЙДЕНО: " . implode(', ', $suspectFields) .
|
||||
". Добавьте это значение в связанную таблицу или исправьте в CSV. " .
|
||||
"Constraint: {$constraintName}";
|
||||
}
|
||||
|
||||
return $baseMsg . "❌ ОШИБКА СВЯЗИ (FK): {$constraintName}. " .
|
||||
"Проверьте значения полей-ссылок. Данные: " . $this->formatRowData($rowData);
|
||||
}
|
||||
|
||||
// Старый формат ошибки
|
||||
if (preg_match('/FOREIGN KEY $$`([^`]+)`$$/', $message, $matches)) {
|
||||
$field = $matches[1];
|
||||
$value = $rowData[$field] ?? 'N/A';
|
||||
return $baseMsg . "Поле '{$field}' = '{$value}': значение не существует в связанной таблице. " .
|
||||
"Данные: " . $this->formatRowData($rowData);
|
||||
return $baseMsg . "❌ Поле '{$field}' = '{$value}': значение НЕ СУЩЕСТВУЕТ в связанной таблице. " .
|
||||
"Создайте это значение в справочнике или исправьте CSV.";
|
||||
}
|
||||
return $baseMsg . "Нарушена связь с другой таблицей. Данные: " . $this->formatRowData($rowData);
|
||||
|
||||
return $baseMsg . "❌ ОШИБКА СВЯЗИ: одно из значений не существует в связанной таблице. " .
|
||||
"Данные: " . $this->formatRowData($rowData);
|
||||
}
|
||||
|
||||
// Duplicate key
|
||||
@@ -473,8 +504,7 @@ private function formatImportError(\PDOException $e, int $lineNumber, array $row
|
||||
if (preg_match('/Duplicate entry \'([^\']+)\' for key \'([^\']+)\'/', $message, $matches)) {
|
||||
$value = $matches[1];
|
||||
$key = $matches[2];
|
||||
return $baseMsg . "Дубликат: значение '{$value}' (ключ '{$key}') уже существует. " .
|
||||
"Данные: " . $this->formatRowData($rowData);
|
||||
return $baseMsg . "Дубликат: значение '{$value}' (ключ '{$key}') уже существует.";
|
||||
}
|
||||
return $baseMsg . "Дубликат записи. Данные: " . $this->formatRowData($rowData);
|
||||
}
|
||||
@@ -483,14 +513,13 @@ private function formatImportError(\PDOException $e, int $lineNumber, array $row
|
||||
if (str_contains($message, "cannot be null") || str_contains($message, "doesn't have a default value")) {
|
||||
if (preg_match('/Column \'([^\']+)\'/', $message, $matches)) {
|
||||
$field = $matches[1];
|
||||
return $baseMsg . "Поле '{$field}' обязательно для заполнения. " .
|
||||
"Данные: " . $this->formatRowData($rowData);
|
||||
return $baseMsg . "Поле '{$field}' обязательно для заполнения (не может быть пустым).";
|
||||
}
|
||||
return $baseMsg . "Не заполнены обязательные поля. Данные: " . $this->formatRowData($rowData);
|
||||
return $baseMsg . "Не заполнены обязательные поля.";
|
||||
}
|
||||
|
||||
// Общая ошибка БД
|
||||
return $baseMsg . "Ошибка БД: " . $message . ". Данные: " . $this->formatRowData($rowData);
|
||||
return $baseMsg . "Ошибка БД: " . $message;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,7 +573,31 @@ private function formatRowData(array $rowData): string
|
||||
// Если не удалось распарсить - возвращаем как есть
|
||||
return $date;
|
||||
}
|
||||
// ✅ ДОБАВЬТЕ ЭТИ ДВА МЕТОДА СЮДА:
|
||||
|
||||
/**
|
||||
* Получает информацию о Foreign Keys таблицы
|
||||
*/
|
||||
public function getForeignKeyInfo(string $schema, string $table): array
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
COLUMN_NAME,
|
||||
CONSTRAINT_NAME,
|
||||
REFERENCED_TABLE_SCHEMA,
|
||||
REFERENCED_TABLE_NAME,
|
||||
REFERENCED_COLUMN_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = :schema
|
||||
AND TABLE_NAME = :table
|
||||
AND REFERENCED_TABLE_NAME IS NOT NULL
|
||||
";
|
||||
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute([':schema' => $schema, ':table' => $table]);
|
||||
|
||||
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
|
||||
private function isNumericType(string $dataType): bool
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user