es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Escapar las comillas en psql para evitar las Inyecciones de SQL.

Estoy haciendo una función para comparar JSONs y luego insertar solo las diferencias en una tabla (trigger).
La función funciona perfectamente cuando ninguno de los registros viene con comillas. Entonces quiero saber cómo escapar estas comillas que pueden venir:

CREATE OR REPLACE FUNCTION public.fnc_compare_jsonb(old_reg jsonb, new_reg jsonb)
 RETURNS jsonb
 LANGUAGE plpgsql
 IMMUTABLE STRICT
AS $function$
declare
    keys record;
    jsonb_return jsonb = '{}'::jsonb;
begin
    for keys in
        select *
        from jsonb_object_keys($1)
    loop
        if $1 -> keys.jsonb_object_keys <> $2 -> keys.jsonb_object_keys then
            jsonb_return = jsonb_return || format('{"%s": "%s"}', keys.jsonb_object_keys, $2 ->> keys.jsonb_object_keys)::jsonb;
        end if;
    end loop;
    return jsonb_return;
end
$function$
;

El error está ocurriendo en la línea:

jsonb_return = jsonb_return || format('{"%s": "%s"}', keys.jsonb_object_keys, $2 ->> keys.jsonb_object_keys)::jsonb;
SQL Error [22P02]: ERROR: sintaxis de entrada no válida para el tipo json
  Detalle: El token ""@" no es válido.
  Donde: datos JSON, línea 1: {"email": "test2"@...
Función PL/pgSQL ecidadao.fnc_compare_jsonb(jsonb,jsonb) línea 11 en la asignación
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para escapar las comillas en los valores de cadena que pueden estar presentes en los objetos JSON de los parámetros de entrada, puedes utilizar la función incorporada jsonb_set() proporcionada por Postgres, que permite establecer un valor específico para una clave en un objeto JSON. En este caso, podemos usarla para reemplazar las comillas por sus versiones escapadas.

    Aquí tienes una versión actualizada de la función que incluye este cambio:

    CREATE OR REPLACE FUNCTION public.fnc_compare_jsonb(old_reg jsonb, new_reg jsonb)
     RETURNS jsonb
     LANGUAGE plpgsql
     IMMUTABLE STRICT
    AS $function$
    declare
        keys record;
        jsonb_return jsonb = '{}';
        new_reg_escaped jsonb; -- variable para almacenar el nuevo objeto JSON con las comillas escapadas
    begin
        new_reg_escaped := new_reg; -- copia el nuevo objeto JSON a la variable
        for keys in
            select *
            from jsonb_object_keys($1)
        loop
            if $1 -> keys.jsonb_object_keys <> new_reg_escaped -> keys.jsonb_object_keys then
                -- reemplaza el valor de cadena por la versión escapada
                new_reg_escaped := jsonb_set(new_reg_escaped, array[keys.jsonb_object_keys], ('"' || replace(new_reg_escaped ->> keys.jsonb_object_keys, '"', '\"') || '"')::jsonb);
                -- agrega el par clave-valor al objeto JSON de retorno
                jsonb_return = jsonb_return || jsonb_build_object(keys.jsonb_object_keys, new_reg_escaped -> keys.jsonb_object_keys);
            end if;
        end loop;
        return jsonb_return;
    end
    $function$
    ;
    

    Los cambios realizados en la función son los siguientes:

    1. Se agregó una nueva variable new_reg_escaped para almacenar el objeto JSON modificado con las comillas escapadas.
    2. Se asignó el valor de new_reg a new_reg_escaped inicialmente, para crear una copia del objeto JSON original.
    3. En el bucle, se reemplazó el valor de cadena del objeto JSON new_reg_escaped por la versión escapada utilizando la función replace() y concatenando con los caracteres necesarios para el formato JSON.
    4. Se utilizó la función jsonb_set() para establecer el valor modificado en la misma clave del objeto new_reg_escaped.
    5. Se construyó el objeto JSON de retorno utilizando el objeto new_reg_escaped modificado.

    Con estos cambios, la función ahora debería poder manejar objetos JSON con valores de cadena que contienen comillas.

Comments are closed.