fix(migrate): robustecer parser SQL y no registrar migración si hubo errores
- Eliminar comentarios de bloque /* */ antes de parsear - Limpiar líneas vacías y comentarios -- sentencia por sentencia - Agregar 'Duplicate key name' y 'Multiple primary key defined' a errores ignorables - Solo registrar en tabla migrations si no hubo errores reales - Si una sentencia falla, continuar con las demás pero marcar had_error=true
This commit is contained in:
+57
-24
@@ -78,42 +78,75 @@ try {
|
||||
|
||||
try {
|
||||
$sql = file_get_contents($file);
|
||||
|
||||
// Dividir en sentencias individuales
|
||||
$statements = array_filter(array_map('trim', explode(';', $sql)));
|
||||
|
||||
$stmt_count = 0;
|
||||
foreach ($statements as $stmt) {
|
||||
// Saltar comentarios y líneas vacías
|
||||
if (empty($stmt) || preg_match('/^--/', $stmt)) {
|
||||
continue;
|
||||
|
||||
// Eliminar comentarios de bloque /* ... */
|
||||
$sql = preg_replace('/\/\*.*?\*\//s', '', $sql);
|
||||
|
||||
// Dividir en sentencias por ; y limpiar
|
||||
$rawStatements = explode(';', $sql);
|
||||
$statements = [];
|
||||
foreach ($rawStatements as $stmt) {
|
||||
// Eliminar líneas de comentario -- y líneas vacías
|
||||
$lines = explode("\n", $stmt);
|
||||
$cleaned = [];
|
||||
foreach ($lines as $line) {
|
||||
$trimmed = trim($line);
|
||||
if ($trimmed !== '' && strpos($trimmed, '--') !== 0) {
|
||||
$cleaned[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = trim(implode("\n", $cleaned));
|
||||
if ($stmt !== '') {
|
||||
$statements[] = $stmt;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt_count = 0;
|
||||
$had_error = false;
|
||||
foreach ($statements as $stmt) {
|
||||
try {
|
||||
$db->execute($stmt);
|
||||
$stmt_count++;
|
||||
} catch (Exception $e) {
|
||||
// Ignorar errores de "ya existe" (IF NOT EXISTS)
|
||||
if (strpos($e->getMessage(), 'Duplicate column') !== false ||
|
||||
strpos($e->getMessage(), 'already exists') !== false) {
|
||||
// Columna ya existe, no es un error real
|
||||
$msg = $e->getMessage();
|
||||
// Ignorar errores de "ya existe" — son idempotentes
|
||||
$ignorable = [
|
||||
'Duplicate column',
|
||||
'already exists',
|
||||
'Duplicate key name',
|
||||
'Multiple primary key defined',
|
||||
];
|
||||
$ignore = false;
|
||||
foreach ($ignorable as $pattern) {
|
||||
if (strpos($msg, $pattern) !== false) {
|
||||
$ignore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($ignore) {
|
||||
echo " ⚠ Ya existe (ignorado): " . substr($msg, 0, 80) . "\n";
|
||||
continue;
|
||||
}
|
||||
throw $e;
|
||||
echo " ✗ Error en sentencia: $msg\n";
|
||||
$had_error = true;
|
||||
// Continuar con las demás sentencias del archivo
|
||||
}
|
||||
}
|
||||
|
||||
// Registrar migración como ejecutada
|
||||
$db->execute(
|
||||
"INSERT INTO migrations (filename) VALUES (?)",
|
||||
[$filename]
|
||||
);
|
||||
|
||||
echo " ✓ Ejecutadas $stmt_count sentencias SQL\n";
|
||||
|
||||
if (!$had_error) {
|
||||
// Registrar migración como ejecutada solo si no hubo errores reales
|
||||
$db->execute(
|
||||
"INSERT INTO migrations (filename) VALUES (?)",
|
||||
[$filename]
|
||||
);
|
||||
echo " ✓ Ejecutadas $stmt_count sentencias SQL — registrada\n";
|
||||
} else {
|
||||
echo " ⚠ Migración con errores — NO registrada (se reintentará en el próximo deploy)\n";
|
||||
}
|
||||
$executed_count++;
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo " ✗ Error en $filename: " . $e->getMessage() . "\n";
|
||||
echo " ✗ Error fatal en $filename: " . $e->getMessage() . "\n";
|
||||
// Continuar con la siguiente migración
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user