Creating a trigger for child table insertion returns confusing error

本秂侑毒 提交于 2019-11-29 12:19:05

Your solution fixes the passing of the row-typed NEW variable. However, you have a sneaky SQL-injection hole in your code, that's particularly dangerous in a SECURITY DEFINER function. User input must never be converted to SQL code unescaped.

Sanitize like this:

CREATE OR REPLACE FUNCTION trg_test_log()
  RETURNS trigger AS
$$
BEGIN
    EXECUTE 'INSERT INTO public.' || quote_ident('testlog_' || NEW.name)
         || ' SELECT ($1).*'
    USING NEW;

    RETURN NULL;
END
$$
LANGUAGE plpgsql SECURITY DEFINER;

Also:

  • OLD is not defined in an INSERT trigger.
  • You don't need a variable. Assignments are comparatively expensive in plpgsql.

The EXECUTE qry USING NEW.* passes in the NEW.* as the arguments to the query. Since NEW.* returns five columns, the query should have $1, $2, $3, $4 and $5 in order to bind the five columns.

You are expecting a single argument ($1) which has five columns in it. I believe that if you change the the line to

EXECUTE qry USING NEW;

it will work as you expect.

With regards to Robert M. Lefkowitz' response, the answer is so simple: NEW as opposed to NEW.*

CREATE OR REPLACE FUNCTION public.test_log() RETURNS trigger AS
$$
DECLARE
    qry text;
BEGIN
    qry := 'INSERT INTO public.testlog_' || NEW.name || ' SELECT ($1).*';

    EXECUTE qry USING NEW;

    RETURN OLD;
END
$$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;

thanks.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!