From 7000464d36c71f1d64f9d153fd5515655ba3dacb Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:27:46 -0500 Subject: [PATCH] =?UTF-8?q?fix(migrate):=20robustecer=20parser=20SQL=20y?= =?UTF-8?q?=20no=20registrar=20migraci=C3=B3n=20si=20hubo=20errores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- database/migrate.php | 81 +++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/database/migrate.php b/database/migrate.php index eaec4c6..1061cdd 100644 --- a/database/migrate.php +++ b/database/migrate.php @@ -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 } }