B
B
beduin012016-03-30 16:51:29
PostgreSQL
beduin01, 2016-03-30 16:51:29

Why am I getting a max_stack_depth error in PostgreSQL when creating a trigger?

It took a very long time, but I could not figure out why I get an error when generating a trigger.
Actually, when inserting data into a table, I need to generate a GUID. I have created a trigger. As I was told, it should fire *before* inserting data, so as not to generate a circular insert when inserting some data generates inserting a new row. However, I don't need a string. To me for a line which I interpose GUID is necessary.
Here is my code:

CREATE TABLE public."USERS"
(
  id integer,
  guid uuid,
  name text
)

Here is the function itself:
CREATE OR REPLACE FUNCTION public.insertguid()
  RETURNS trigger AS
$BODY$BEGIN
    INSERT INTO "USERS" ("guid") VALUES (md5(random()::text || clock_timestamp()::text)::uuid);
    return new;
END$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION public.insertguid()
  OWNER TO postgres;

The trigger itself:
CREATE TRIGGER createGUID BEFORE INSERT ON "USERS" EXECUTE PROCEDURE insertGUID();

However, when querying:
INSERT INTO "USERS"(name) VALUES ('foo1');
I get:
ОШИБКА:  превышен предел глубины стека
HINT:  Увеличьте параметр конфигурации "max_stack_depth" (текущее значение 2048 КБ), предварительно убедившись, что ОС предоставляет достаточный размер стека.
CONTEXT:  SQL-оператор: "INSERT INTO "USERS" ("guid") VALUES (md5(random()::text || clock_timestamp()::text)::uuid)"
функция PL/pgSQL insertguid(), строка 2, оператор SQL-оператор
SQL-оператор: "INSERT INTO "USERS" ("guid") VALUES (md5(random()::text || clock_timestamp()::text)::uuid)"

Answer the question

In order to leave comments, you need to log in

2 answer(s)
T
terrier, 2016-03-30
@terrier

Your insert trigger calls an insert (which calls an insert).
You need to firstly declare it FOR EACH ROW,
secondly you can modify new
new.guid = <your expression>

A
Alexander Shelemetiev, 2016-04-03
@zoroda

Let's explain. The trigger in your case is called before the data is inserted. The NEW variable is automatically passed to it, which contains the values ​​to be inserted: NEW.id, NEW.guid, NEW.name.
And so this trigger can simply change interposed values. For example, in a trigger function, you change the uuid value to whatever you want:
after that, the trigger should return the modified values. NEW:
For inserting into the table, what the trigger returned, i.e. NEW, including the NEW.guid you specified in the trigger function.
Perhaps a simpler solution will suit: declare the default value of the uuid field in the table:

CREATE TABLE public."USERS"
(
  id integer,
  guid uuid default md5(random()::text || clock_timestamp()::text)::uuid,
  name text
)

in that case it is possible to do without triggers.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question