Question

I have defined a trigger in PostgreSQL 9.3 that checks the length of attribute_group_attribute.default_value based on the value of attribute_type.max_length:


CREATE OR REPLACE FUNCTION trigger_function()
  RETURNS trigger AS 
$BODY$
DECLARE
    is_longer_than_max_length BOOLEAN;
BEGIN
    IF (NEW.default_value IS NOT NULL) THEN
        SELECT length(NEW.default_value) > attribute_type.max_length 
        INTO is_longer_than_max_length FROM attribute_group_attribute 
        JOIN attribute ON NEW.attribute_id = attribute.id JOIN attribute_type 
        ON attribute.attribute_type_id = attribute_type.id;

        IF (is_longer_than_max_length) THEN
            RAISE EXCEPTION 'Attribute type with id % has max length of %, 
            while attribute default value % has a length of %.', 
            attribute_type.id, attribute_type.max_length, NEW.default_value,
            length(NEW.default_value) USING ERRCODE='20808';
        END IF;
    END IF;
    RETURN NEW;
END
$BODY$
  LANGUAGE 'plpgsql' SECURITY INVOKER
;

CREATE TRIGGER trigger_name BEFORE INSERT OR UPDATE ON attribute_group_attribute 
FOR EACH ROW EXECUTE PROCEDURE trigger_function()
;

The trigger works fine on INSERT and raises the EXCEPTION. But on UPDATE I get this error:


ERROR:  missing FROM-clause entry for table "attribute_type" at character 8
QUERY:  SELECT attribute_type.id
CONTEXT:  PL/pgSQL function trg_func_attr_group_attr_attr_type() line 8 at RAISE
Was it helpful?

Solution

With the help of Igor Romanchenko's suggestions I came up with this solution that does what I want:


CREATE OR REPLACE FUNCTION trigger_function()
  RETURNS trigger AS 
$BODY$
DECLARE
    attribute_type_id numeric(12,0);
    attribute_type_max_length numeric(9,0);
    is_longer_than_max_length BOOLEAN;
BEGIN
    IF (NEW.default_value IS NOT NULL) THEN
        SELECT attribute_type.id, attribute_type.max_length, 
        length(NEW.default_value) > attribute_type.max_length 
        INTO attribute_type_id, attribute_type_max_length, 
        is_longer_than_max_length FROM attribute_group_attribute 
        JOIN attribute ON NEW.attribute_id = attribute.id JOIN attribute_type 
        ON attribute.attribute_type_id = attribute_type.id;
        IF (is_longer_than_max_length) THEN
            RAISE EXCEPTION 'Attribute type with id % has max length of %, while 
            attribute default value % has a length of %.', attribute_type_id,
            attribute_type_max_length, NEW.default_value, 
            length(NEW.default_value) USING ERRCODE='20808';
        END IF;
    END IF;
    RETURN NEW;
END
$BODY$
  LANGUAGE 'plpgsql' SECURITY INVOKER
;

CREATE TRIGGER trigger_name BEFORE INSERT OR UPDATE ON attribute_group_attribute 
FOR EACH ROW EXECUTE PROCEDURE trigger_function()
;

OTHER TIPS

The query:

SELECT length(NEW.default_value) > attribute_type.max_length 
INTO is_longer_than_max_length FROM attribute_group_attribute 
JOIN attribute ON NEW.attribute_id = attribute.id JOIN attribute_type 
ON attribute.attribute_type_id = attribute_type.id;

Does not make sens. There is attribute_group_attribute in FROM clause, but there are no filters for this table.

You need something like:

SELECT length(NEW.default_value) > attribute_type.max_length 
INTO is_longer_than_max_length 
FROM attribute 
JOIN attribute_type ON attribute.attribute_type_id = attribute_type.id
WHERE NEW.attribute_id = attribute.id;

Also you need to select attribute_type.id, attribute_type.max_length into function variables before you can use them in RAISE EXCEPTION statement.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top