Esto debería hacerlo:
CREATE OR REPLACE FUNCTION device_bid_modifiers_count_per()
RETURNS TRIGGER AS
$func$
DECLARE
devices_count int := device_types_count();
table_name regclass := TG_ARGV[0];
column_name text := TG_ARGV[1];
BEGIN
LOCK TABLE device_types IN EXCLUSIVE MODE;
EXECUTE format('LOCK TABLE %s IN EXCLUSIVE MODE', table_name);
IF TG_OP = 'DELETE' THEN
PERFORM validate_bid_modifiers_count(table_name
, column_name
, (row_to_json(OLD) ->> column_name)::bigint
, devices_count);
ELSE
PERFORM validate_bid_modifiers_count(table_name
, column_name
, (row_to_json(NEW) ->> column_name)::bigint
, devices_count);
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
La causa inmediata del mensaje de error fue el SELECT
externo . Sin objetivo, debe reemplazarlo con PERFORM
en plpgsql. Pero el PERFORM
interno en la cadena de consulta pasada a EXECUTE
también estaba mal. PERFORM
es un comando plpgsql, no válido en una cadena SQL pasada a EXECUTE
, que espera código SQL. Tienes que usar SELECT
allá. Finalmente OLD
y NEW
no son visibles dentro de EXECUTE
y cada uno plantearía una excepción propia de la forma en que lo tenía. Todos los problemas se solucionan dejando caer EXECUTE
.
Una forma sencilla y rápida de obtener el valor de un nombre de columna dinámico de los tipos de fila OLD
y NEW
:enviar a json
, luego puede parametrizar el nombre de la clave como se muestra. Debería ser un poco más simple y rápido que la alternativa con SQL dinámico, que también es posible, como:
...
EXECUTE format('SELECT validate_bid_modifiers_count(table_name
, column_name
, ($1.%I)::bigint
, devices_count)', column_name)
USING OLD;
...
Relacionado:
- Obtener valores de diferentes columnas en un disparador genérico
- Activar con nombre de campo dinámico
Aparte:no estoy seguro de por qué necesita las cerraduras pesadas.
Aparte 2:Considere escribir una función de disparador separada para cada disparador en su lugar. DDL más ruidoso, pero más simple y rápido de ejecutar.