Pega una consulta o un script: cada sentencia se revisa como texto en este navegador, con los comentarios y las cadenas enmascarados para no confundir palabras clave con SQL real. Los hallazgos mantienen el tipo de sentencia a través de un WITH, exigen un WHERE de nivel superior para DELETE y UPDATE y cuentan los marcadores de parámetros fuera de literales y conversiones.
Se ejecuta localmente en tu navegadorLa página divide el script pegado en sentencias y revisa cada una como texto: la palabra clave inicial se lee en el nivel superior, así que WITH old AS (...) DELETE FROM users se informa como DELETE, no como SELECT. Nada se convierte en un plan de ejecución y nada se envía a una base de datos.
Las comprobaciones cubren lo que una revisión de código mira primero: DELETE y UPDATE sin WHERE en la propia sentencia, DROP y TRUNCATE, SELECT * y SELECT sin límite de filas, un literal comparado en un filtro, un 1=1 u OR TRUE de nivel superior, un marcador de plantilla ${...} y un valor montado con concatenación de cadenas.
Se cuentan como escrituras INSERT, UPDATE, DELETE, MERGE, REPLACE, CREATE, ALTER, DROP y TRUNCATE. Un DELETE o UPDATE sin WHERE en la propia sentencia es un hallazgo de peligro: un WHERE dentro de una subconsulta no protege la escritura exterior. DROP y TRUNCATE son hallazgos de peligro por sí mismos; el resto de escrituras son avisos.
En un SELECT se busca un asterisco en la lista de columnas (incluido t.*) y un límite de filas: LIMIT, FETCH FIRST o NEXT ... ROWS ONLY, TOP n y ROWNUM <= n cuentan, de modo que la nota informativa de falta de límite solo aparece cuando el SELECT podría devolver un número ilimitado de filas.
El recuento de marcadores cubre ?, $1, :name y @name fuera de comentarios y cadenas; una conversión como created_at::text y un identificador como @@ROWCOUNT no se cuentan. Un literal comparado en un filtro WHERE, AND u OR es un aviso que apunta a la sintaxis de parámetros de tu controlador.
Dos patrones de construcción de cadenas se informan por separado: un marcador de plantilla ${...} indica que un valor se interpola en la sentencia, y una concatenación como un literal más un identificador indica que el texto se arma fuera del controlador. Ninguno es un parámetro enlazado, y esa es la diferencia que importa para el texto que llega al servidor.
El divisor entiende comillas dobladas y escapes con barra invertida de MySQL, identificadores entre comillas dobles y acentos graves, comentarios -- y /* */, comentarios #, cuerpos entre $$ de PostgreSQL y directivas DELIMITER, así que un apóstrofo escapado o un cuerpo de función no producen un recuento falso. Un script con más de una sentencia genera un aviso y cada hallazgo lleva su número de sentencia.
La página no se conecta a ninguna base de datos, no ejecuta nada y no puede ver tu esquema, permisos, seguridad a nivel de fila ni transacciones: una sentencia que pasa aquí todavía puede ser destructiva en tu entorno. Úsala como precomprobación de texto antes de una revisión, junto a EXPLAIN y a la lectura del código que la genera.