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:
Lizandro Guarnizo
2026-03-12 09:27:46 -05:00
parent 28307f44d1
commit 7000464d36
+57 -24
View File
@@ -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
}
}