CodeGym /Cursos /SQL SELF /Introducción a la depuración en PL/pgSQL

Introducción a la depuración en PL/pgSQL

SQL SELF
Nivel 55 , Lección 0
Disponible

Imagina que has creado una función o procedimiento bastante complejo. Ya te imaginas lo bien que va tu base de datos, pero de repente — ¡zas! — los datos no son los que esperabas, las consultas van lentas y tu jefe empieza a ponerse nervioso. Es aquí donde entra la depuración.

La depuración en PL/pgSQL sirve para:

  • Encontrar errores de lógica, por ejemplo, cuando una función devuelve algo que no esperabas.
  • Entender qué pasa con los datos de entrada incorrectos. Porque a veces los usuarios de la base de datos meten no solo datos, sino... ¡algo totalmente incomprensible!
  • Solucionar problemas de rendimiento. Porque el código hecho a la carrera puede ir tan lento como una tortuga buscando Wi-Fi en medio del desierto del Sahara.

En serio, depurar no es solo buscar y arreglar bugs. Es una forma de mejorar tu código, hacerlo más rápido, eficiente y legible.

Enfoques principales para depurar PL/pgSQL

La depuración en PL/pgSQL se puede hacer de varias formas. Vamos a verlas una por una.

  1. Uso de herramientas integradas de PostgreSQL

PostgreSQL trae varias opciones integradas para diagnosticar, incluyendo funciones de logging (RAISE NOTICE y RAISE EXCEPTION), y también el análisis del plan de ejecución de consultas (EXPLAIN ANALYZE). Estas herramientas te ayudan a entender qué pasa dentro de tu función.

  1. Logging usando RAISE NOTICE

RAISE NOTICE es tu colega si quieres ver qué datos pasan por la función, en qué momento algo falla, o chequear valores de variables. A diferencia de RAISE EXCEPTION, no interrumpe la ejecución de la función. Por ejemplo, puedes mostrar el contenido de una variable en cada paso.

DO $$
DECLARE
    counter INT := 0;
BEGIN
    FOR counter IN 1..5 LOOP
        RAISE NOTICE 'Valor actual del contador: %', counter;
    END LOOP;
END $$;

Este código muestra los valores de counter del 1 al 5. Magia sencilla, pero súper útil para depurar.

  1. Uso de herramientas externas

La depuración de PL/pgSQL también se puede hacer con herramientas como pgAdmin (con interfaz gráfica). Te permite poner breakpoints y ver los valores de las variables en tiempo real. Si eres de los que prefieren asistentes visuales, pgAdmin será tu mejor aliado.

Etapas de la depuración

Cuando empezamos a depurar una función o procedimiento, es importante seguir un orden. Vamos a ver cada etapa con más detalle:

  1. Análisis de los datos de entrada

Lo primero que hay que mirar son los datos de entrada. Asegúrate de que los datos que recibe tu función no tengan errores o valores raros. Por ejemplo, puedes chequear todos los parámetros de entrada usando RAISE NOTICE:

CREATE FUNCTION check_input(x INTEGER) RETURNS VOID AS $$
BEGIN
    IF x IS NULL THEN
        RAISE EXCEPTION '¡El valor de entrada no puede ser NULL!';
    END IF;
    RAISE NOTICE 'Valor de entrada: %', x;
END;
$$ LANGUAGE plpgsql;

Este ejemplo muestra cómo avisar a los usuarios sobre problemas con los datos de entrada.

  1. Comprobar la ejecución de cada etapa

Divide tu función en bloques lógicos y mete RAISE NOTICE en los puntos clave. Así puedes ver exactamente dónde falla algo.

CREATE FUNCTION calculate_discount(price NUMERIC, discount NUMERIC) RETURNS NUMERIC AS $$
BEGIN
    RAISE NOTICE 'Inicio de la función: precio %, descuento %', price, discount;

    IF price <= 0 THEN
        RAISE EXCEPTION '¡El precio no puede ser negativo ni igual a cero!';
    END IF;

    IF discount < 0 OR discount > 100 THEN
        RAISE EXCEPTION '¡El descuento debe estar entre 0 y 100!';
    END IF;

    RETURN price - (price * discount / 100);
END;
$$ LANGUAGE plpgsql;

Aquí en cada etapa de la depuración se muestran mensajes útiles sobre el estado del proceso.

  1. Optimización y solución de problemas
  2. Una vez que has encontrado el error, arréglalo. Si el problema es de rendimiento, usa herramientas de análisis como EXPLAIN ANALYZE para optimizar las consultas.

Aplicación práctica de las habilidades de depuración

Vamos a ver un caso real: tenemos una función que añade un registro a una tabla y devuelve el identificador generado. Parece lógico y sencillo, pero a veces la función falla y queremos saber por qué.

Función original:

CREATE FUNCTION add_student(name TEXT, age INTEGER) RETURNS INTEGER AS $$
DECLARE
    new_id INTEGER;
BEGIN
    INSERT INTO students (name, age) VALUES (name, age) RETURNING id INTO new_id;
    RETURN new_id;
END;
$$ LANGUAGE plpgsql;

Si llamas a esta función con datos incorrectos, por ejemplo, age < 0, te dará un error. Vamos a mejorarla usando herramientas de depuración.

Función mejorada con logging:

CREATE FUNCTION add_student(name TEXT, age INTEGER) RETURNS INTEGER AS $$
DECLARE
    new_id INTEGER;
BEGIN
    -- Logueamos los datos de entrada
    RAISE NOTICE 'Añadiendo estudiante: nombre %, edad %', name, age;

    -- Comprobamos que la edad sea válida
    IF age < 0 THEN
        RAISE EXCEPTION '¡La edad no puede ser negativa!';
    END IF;

    -- Añadimos el estudiante y devolvemos su ID
    INSERT INTO students (name, age) VALUES (name, age) RETURNING id INTO new_id;

    -- Logueamos el éxito
    RAISE NOTICE 'Estudiante añadido con ID %', new_id;

    RETURN new_id;
END;
$$ LANGUAGE plpgsql;

Ahora, si hay un error, sabrás exactamente qué ha pasado gracias a los mensajes que saca RAISE NOTICE.

Consejos útiles para terminar

  1. No olvides quitar los logs innecesarios en el código de producción. RAISE NOTICE es genial para depurar, pero si lo dejas siempre puede llenar los logs en producción.
  2. Trabaja con trozos pequeños de código. Si la función es demasiado compleja, divídela en partes. Así es mucho más fácil depurar.
  3. Practica seguido. Cuanto más escribas y depures código, más rápido serás encontrando y arreglando bugs.

La depuración es como un juego de detectives, solo que en vez de lupa tienes consultas SQL y lógica PL/pgSQL. La maestría llega con la experiencia, pero cada bug que arreglas te hace un poco mejor!

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION