4

I am trying to make simple trigger function (Postgresql) but I am getting same error 'function did not return any row' in all these cases (just simple examples):

New:

UPDATE somewhere SET something = something - 1;
RETURN NEW;

Old:

UPDATE somewhere SET something = something - 1;
RETURN OLD;

What should I return when I call this function "before delete"? ("after insert/update" works well)

Tyvm for tips!

Full code as requested: Function:

CREATE OR REPLACE FUNCTION pictogram_frequency_on_delete()
RETURNS trigger AS
$BODY$
DECLARE

new_frequency RECORD;
target_unit RECORD;
current_row RECORD;
units_with_same_type RECORD;
what RECORD; 

BEGIN
SET search_path TO 'myScheme';

CASE TG_OP
WHEN 'DELETED' THEN what := OLD;
ELSE what:= OLD;
END CASE;

SELECT unit_type_uid INTO STRICT target_unit 
FROM unit 
WHERE unit_uid = what.unit_uid;

SELECT count(*) AS exists INTO STRICT current_row 
FROM unit_type_pictogram utp 
WHERE utp.pictogram_uid = what.pictogram_uid 
AND utp.unit_type_uid = target_unit.unit_type_uid;

IF (current_row.exists = 0) THEN
    RETURN what; /* return new/old doesnt work too */
END IF;

UPDATE unit_type_pictogram utp 
SET frequency = frequency - 1
WHERE utp.pictogram_uid = what.pictogram_uid 
AND utp.unit_type_uid = target_unit.unit_type_uid;

RETURN what; /* return new/old doesnt work too */

END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

Trigger:

CREATE TRIGGER on_delete_frequency
BEFORE DELETE
ON unit_pictogram
FOR EACH ROW
  EXECUTE PROCEDURE pictogram_frequency_on_delete();
Úca
  • 43
  • 1
  • 6

2 Answers2

5

From documentation:

Trigger functions invoked by per-statement triggers should always return NULL. Trigger functions invoked by per-row triggers can return a table row (a value of type HeapTuple) to the calling executor, if they choose. A row-level trigger fired before an operation has the following choices:

  • It can return NULL to skip the operation for the current row. This instructs the executor to not perform the row-level operation that invoked the trigger (the insertion, modification, or deletion of a particular table row).

  • For row-level INSERT and UPDATE triggers only, the returned row becomes the row that will be inserted or will replace the row being updated. This allows the trigger function to modify the row being inserted or updated.

A row-level BEFORE trigger that does not intend to cause either of these behaviors must be careful to return as its result the same row that was passed in (that is, the NEW row for INSERT and UPDATE triggers, the OLD row for DELETE triggers).


EDIT

Try something like this:

CREATE OR REPLACE FUNCTION pictogram_frequency_on_delete()
RETURNS trigger AS
$BODY$
BEGIN
  UPDATE unit_type_pictogram AS utp
    SET frequency = frequency - 1
    FROM unit
    WHERE utp.pictogram_uid = OLD.pictogram_uid
      AND unit_uid = OLD.unit_uid
      AND utp.unit_type_uid = unit.unit_type_uid;
  RETURN OLD;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
Usagi Miyamoto
  • 6,196
  • 1
  • 19
  • 33
3

You should RETURN OLD;.

Your function must be defined as RETURNS trigger.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
  • I am using "RETURN OLD" but debugger returns error "'function did not return any row". How do you mean "Must be defined as returns trigger"? – Úca Jul 11 '17 at 12:28