Alias column name in Postgres notify - postgresql

I am using trigger in Postgres database to call function and send newly inserted row to NodeJs application
CREATE OR REPLACE FUNCTION triggerFunction() RETURNS trigger AS $$
DECLARE
BEGIN
PERFORM pg_notify('tableName', row_to_json(NEW)::text );
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
This returns the whole row in json format. However I need to change one of the column name while this row is returned.
Unfortunately AS keywork doesnt work in the row to json with NEW.COLUMN_NAME AS NEW_COLUMN. How can we achieve the solution for this?

CREATE OR REPLACE FUNCTION triggerFunction() RETURNS trigger AS $$
DECLARE
ret json;
BEGIN
select row_to_json(x) into ret from
(select NEW.abc as def, NEW.jkl, NEW.col3) x;
PERFORM pg_notify('tableName', ret::text );
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Related

pg_notify with a subset of a row

Hi I am trying to work out how to return a subset of a new row as json to a pg_notify function.
I am currently using
create or replace function public.notify_site()
returns trigger
language plpgsql
as $function$
begin
perform pg_notify('ppsite', row_to_json(NEW)::text);
RETURN new;
END;
$function$;
which works fine returning the entire row of data when the after insert trigger for the table fines, however, what I'm trying to do is return just a subset of NEW rather than the entire thing. It would be really cool if I could return the result of a select on NEW or something similar. Is this possible or does my receiving application need to sort the data out instead?
To be clear, I want to return json with say
NEW.c1, NEW.c2, NEW.c5 rather than the entire row of about 50 values.
Ta.
You can define the projection you want from the NEW record:
CREATE OR REPLACE FUNCTION public.notify_site()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
declare
my_record record;
begin
select NEW.id as id, NEW.some_data as some_data INTO my_record;
perform pg_notify('pp_site', row_to_json(my_record)::text);
return NEW;
end;
$function$
;

postgresql - trigger function with condition

I'm trying to create a trigger with a condition. Based on the geom length I want the attribute "nom" (= name) to be written in upper case or lower case.
here's what I have:
CREATE OR REPLACE FUNCTION public.test_upper_lower()
RETURNS trigger AS
$BODY$
BEGIN
NEW.dummy:= (ST_Length(new.geom));
if (SELECT dummy FROM ligne_ligne)>100
then NEW.nom:= LOWER(nom) FROM ligne_ligne;
else NEW.nom:= UPPER(nom) FROM ligne_ligne;
end if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
DROP trigger IF EXISTS test_upper_lower on public.ligne_ligne;
CREATE trigger test_upper_lower BEFORE INSERT OR UPDATE on public.ligne_ligne
FOR EACH ROW
EXECUTE PROCEDURE public.test_upper_lower();
With this I have a "more than one row returned by a subquery" error
Based on other questions on this forum I tried it using case instead of if and using when in the trigger itself not the function but neither are working
Any ideas ?
Thanks
You don't need (or can actually) use SELECT statements to access data from the inserted row.
The part SELECT dummy FROM ligne_ligne returns all rows from that table - not just from the one relevant to the trigger.
As you just want to check the value you just calculated, simply use new.dummy at that point:
CREATE OR REPLACE FUNCTION public.test_upper_lower()
RETURNS trigger AS
$BODY$
BEGIN
NEW.dummy:= ST_Length(new.geom);
if new.dummy > 100 then --<< no SELECT necessary
NEW.nom:= LOWER(new.nom); --<< no "FROM", just access the value
else
NEW.nom:= UPPER(new.nom);
end if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;

Postgres function, getting "query has no destination for result data", don't want to use table result type

I am writing a simple postgres function. The result of this function should be a row of the "events" table. I have the following:
create or replace function featured_event() returns setof events as
$$
begin
select events.* from events where featured is true;
end
$$ LANGUAGE plpgsql;
I don't want to hardcode the columns, but instead use the structure from the existing table as the return type.
This is not a duplicate of Function with SQL query has no destination for result data as I do not want to use the table result type.
Use SQL function:
create or replace function featured_event() returns setof events as
$$
select events.* from events where featured is true;
$$ LANGUAGE sql;
In plpgsql you should use return query:
create or replace function featured_event_plpgsql() returns setof events as
$$
begin
return query select events.* from events where featured is true;
end;
$$ LANGUAGE plpgsql;

Postgres Stored procedure in select statement cannot get the datas

I am trying to get the data from the Database use function of select prison();.but i got error .Please advise me.
CREATE OR REPLACE FUNCTION prison() RETURNS refcursor AS $$
DECLARE
ref refcursor;
BEGIN
OPEN ref FOR SELECT round,ben_sc,ben_st FROM prison_issue;
RETURN ref;
END;
$$ LANGUAGE plpgsql;
and calling like this
select prison();
also i tried.but cannot executed the rows.
BEGIN;
SELECT prison();
-- Returns: <unnamed portal 2>
FETCH ALL IN "<unnamed portal 24>";
COMMIT;
There is no need for a PL/pgSQL function for this:
CREATE OR REPLACE FUNCTION prison()
RETURNS setof prison_issue
AS $$
SELECT * FROM prison_issue;
$$ LANGUAGE sql;
You also need to use:
select * from prison();
to retrieve the data, do not use select prison() (which only returns a single record, not multiple rows)
You didn't show us your definition of the table prison_issue if you don't want to return all columns you need something like this:
CREATE OR REPLACE FUNCTION prison()
RETURNS table (round integer, ben_sc text, ben_st text)
AS $$
SELECT SELECT round,ben_sc,ben_st FROM prison_issue;
$$ LANGUAGE sql;
You will need to adjust the part table (round integer, ben_sc text, ben_st text) to match the data type of the columns you select.
Below is an example code.I have assumed the data types.Replace with the real ones.
CREATE OR REPLACE FUNCTION prison() RETURNS TABLE(round numeric,ben_sc character varying,ben_st character varying) AS $$
BEGIN
RETURN QUERY SELECT p.round,p.ben_sc,p.ben_st FROM prison_issue p;
END;
$$ LANGUAGE plpgsql;

How to log delete queries on Postgresql?

I created a function which writes information about table deletions.
And another function which simply adds a trigger call after delete.
But I would like to store the whole row as string into my table.
According to Postgresql Documentation it should work by adding "OLD.*" into a text based column. But it fails telling me that I try to put too many columns into this table.
OLD is from type RECORD. And i want to have it in my text field like "value1,value2,value3" or it could be "colname:value,colname2:value". I dont care, I just want to see the row which has been deleted.
Another approach can be to log all delete queries from pg_stat_activity. But I don't know how to do that. Simply accessing pg_stat_activity every second would cause too much traffic I guess.
My table is simple:
create table delete_history (date timestamp, tablename varchar(100), data text);
This is my function:
CREATE or REPLACE FUNCTION ondelete() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO delete_history VALUES (CURRENT_TIMESTAMP, TG_TABLE_NAME, OLD.*);
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
This is my trigger:
CREATE OR REPLACE FUNCTION history_create_triggers() RETURNS void
AS $$
DECLARE
r RECORD;
BEGIN
FOR r IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_type='BASE TABLE' LOOP
EXECUTE 'CREATE TRIGGER log_history AFTER DELETE ON public.' || r.table_name || ' FOR EACH ROW EXECUTE PROCEDURE ondelete();';
END LOOP;
END;
$$ LANGUAGE plpgsql;
You can convert type record into text:
CREATE or REPLACE FUNCTION ondelete() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO delete_history VALUES (CURRENT_TIMESTAMP, TG_TABLE_NAME, OLD::text);
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
sql fiddle demo
another approach could be converting your row into JSON with row_to_json function (if you have version 9.2):
CREATE or REPLACE FUNCTION ondelete() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO delete_history VALUES (CURRENT_TIMESTAMP, TG_TABLE_NAME, row_to_json(OLD));
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
sql fiddle demo
Another approach can be convert your data to hstore
CREATE or REPLACE FUNCTION ondelete() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO delete_history VALUES (CURRENT_TIMESTAMP, TG_TABLE_NAME, hstore(OLD));
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
I can't test it now - sqlfiddle is not allowing to use hstore.