Trigger close the pg Admin? - postgresql

I created a trigger fk_pay_trigger on INSERT
CREATE TRIGGER fk_pay_trigger
BEFORE INSERT ON fk_payment_temp
FOR EACH ROW
EXECUTE PROCEDURE add_insert_trigger_fk()
and function attach is:
-- Function: add_insert_trigger_fk()
-- DROP FUNCTION add_insert_trigger_fk();
CREATE OR REPLACE FUNCTION add_insert_trigger_fk()
RETURNS trigger AS
$BODY$
Declare
begin
if (TG_TABLE_NAME = 'fk_payment_temp') then
if (TG_OP = 'INSERT') then
Insert into fk_payment_temp_backup values(now(),NEW.settlement_ref_no, NEW.order_type, NEW.fulfilment_type, NEW.seller_sku, NEW.wsn,
NEW.order_id, NEW.order_item_id, NEW.order_date, NEW.dispatch_date, NEW.delivery_date,
NEW.cancellation_date, NEW.settlement_date, NEW.order_status, NEW.quantity, NEW.order_item_value,
NEW.sale_transaction_amount, NEW.discount_transaction_amount, NEW.refund,
NEW.protection_fund, NEW.total_marketplace_fee, NEW.service_tax, NEW.settlement_value,
NEW.commission_rate, NEW.commission, NEW.payment_rate, NEW.payment_fee, NEW.fee_discount,
NEW.cancellation_fee, NEW.fixed_fee, NEW.emi_fee, NEW.total_weight, NEW.shipping_fee,
NEW.reverse_shipping_fee, NEW.shipping_zone, NEW.token_of_apology, NEW.pick_and_pack_fee,
NEW.storage_fee, NEW.removal_fee, NEW.invoice_id, NEW.invoice_date, NEW.invoice_amount,
NEW.sub_category, NEW.total_offer_amount, NEW.my_offer_share, NEW.flipkart_offer_share);
return NEW;
END if;
End if ;
return null;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Its working fine. but the problem is :
when trigger perform . PG admin Shut down automatically .
I dont know what happen . Is there is any problem in my code or any problem ?

Related

Build a trigger that avoids to update the values of one column

I have a table in PostgretSQL. I want to build a trigger that avoids to update colb1 column. This column has five alternatives: Rea, Can, Loa, Mul, Alm. So the trigger doesn't let upload values from Rea to Can.
I've built this function but this is fail.
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS trigger AS
$BODY$
BEGIN
new.colb1.tabl1 = 'Rea' := old.colb1.tabl1 = 'Can';
new.colb1.tabl1 = 'Can' := old.colb1.tabl1 = 'Rea';
RETURN new;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
DROP TRIGGER IF EXISTS trigger_name ON table1;
CREATE TRIGGER trigger_name BEFORE UPDATE ON table1
FOR EACH ROW EXECUTE PROCEDURE example_trigger();
I edited my post with changes:
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS TRIGGER AS
$$
BEGIN
NEW.colb1 := OLD.colb1;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER not_changes
BEFORE UPDATE
ON tabl1
FOR EACH ROW
EXECUTE PROCEDURE example_trigger();
It's not exactly that I want because I want that the values Loa, Mul and Alm can be update.
A slight modification of your function to stop the modification of colb1 from Rea or Can to Can or Rea.
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS TRIGGER AS
$$
BEGIN
IF OLD.colb1 in ('Rea', Can') AND NEW.colb1 IN ('Rea', 'Can') THEN
NEW.colb1 := OLD.colb1;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
This will not stop a user from using an intermediate UPDATE to change to one of Loa/Mul/Alm and then to either Rea or Can

Postgres Trigger is not firing. Syntax help is appreciated

I'm trying to mark a boolean column on a different table to true upon the insertion of a matching record.
Here's what I've got:
CREATE or replace FUNCTION mark_as_sold() RETURNS trigger AS
$BODY$
BEGIN
UPDATE listing
set listing.sold = true;
WHERE listing.id = NEW.listing_id;
RETURN NEW;
END
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER update_child_after_update
AFTER INSERT
ON transaction
FOR EACH ROW
EXECUTE PROCEDURE mark_as_sold();
When I create a record on the transaction table, nothing happens. I'm stumped. Any help is greatly appreciated.
I figured it out. I was messing up my relations. Here's the proper code:
CREATE OR REPLACE FUNCTION mark_as_sold()
RETURNS TRIGGER
AS $$
BEGIN
UPDATE listing
set sold = true
WHERE listing.id = NEW.listing_id;
RETURN NEW;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER test_trigger BEFORE INSERT OR UPDATE
ON "transaction"
FOR EACH ROW EXECUTE PROCEDURE mark_as_sold();

POSTGRESQL trigger troubles

Wrote this code. Problem with this code is that it's doing nothing. Should update OTB_Name when I'm updating table, but nothing happens.
Can somebody tell me where my problem is?
CREATE OR REPLACE FUNCTION public.demand_lom_ar5_tracker()
RETURNS trigger AS $demand_lom_ar5_tracker$
BEGIN
-- INSERT
IF (TG_OP = 'INSERT') THEN
UPDATE public.demand_lom_ar5
SET "OTB_Name" = ar5_area_otb."OTB_Name"
FROM mapinfo.public.ar5_area_otb
WHERE ST_Contains (mapinfo.public.demand_lom_ar5."SP_GEOMETRY", mapinfo.public.ar5_area_otb."SP_GEOMETRY");
RETURN NULL;
-- UPDATE
ELSIF (TG_OP = 'UPDATE') THEN
UPDATE public.demand_lom_ar5
SET "OTB_Name" = ar5_area_otb."OTB_Name"
FROM mapinfo.public.ar5_area_otb
WHERE NEW."MI_PRINX" = OLD."MI_PRINX" and ST_Contains (mapinfo.public.demand_lom_ar5."SP_GEOMETRY", mapinfo.public.ar5_area_otb."SP_GEOMETRY");
RETURN NULL;
END IF;
END;
$demand_lom_ar5_tracker$ LANGUAGE plpgsql;
--apply the trigger:
DROP TRIGGER IF EXISTS trg_demand_lom_ar5_tracker
ON public.demand_lom_ar5;
CREATE TRIGGER trg_demand_lom_ar5_tracker
AFTER INSERT OR UPDATE ON public.demand_lom_ar5
FOR EACH ROW EXECUTE PROCEDURE public.demand_lom_ar5_tracker();

How should I extract duplicated logic in a Postgres function?

I have a Postgres function with a lot of duplicated logic. If I were writing this in, say, Ruby, I would extract the duplicated logic into a few private helper methods. But there doesn't seem to be an equivalent of "private methods" in Postgres.
Original Function
CREATE OR REPLACE FUNCTION drop_create_idx_constraint(in_operation varchar, in_table_name_or_all_option varchar) RETURNS integer AS $$
DECLARE
cur_drop_for_specific_tab CURSOR (tab_name varchar) IS SELECT drop_stmt FROM table_indexes WHERE table_indexes.table_name = table_name_to_drop;
cur_drop_for_all_tab CURSOR IS SELECT drop_stmt FROM table_indexes;
cur_create_for_specific_tab CURSOR (tab_name varchar) IS SELECT recreate_stmt FROM table_indexes WHERE table_indexes.table_name = table_name_to_drop;
cur_create_for_all_tab CURSOR IS SELECT recreate_stmt FROM table_indexes;
BEGIN
IF upper(in_operation) = 'DROP' THEN
IF upper(in_table_name_or_all_option) ='ALL' THEN
FOR table_record IN cur_drop_for_all_tab LOOP
EXECUTE table_record.drop_stmt;
END LOOP;
ELSE
FOR table_record IN cur_drop_for_specific_tab(in_table_name_or_all_option) LOOP
EXECUTE table_record.drop_stmt;
END LOOP;
END IF;
ELSIF upper(in_operation) = 'CREATE' THEN
IF upper(in_table_name_or_all_option) ='ALL' THEN
FOR table_record IN cur_create_for_all_tab LOOP
EXECUTE table_record.recreate_stmt;
END LOOP;
ELSE
FOR table_record IN cur_create_for_specific_tab(in_table_name_or_all_option) LOOP
EXECUTE table_record.recreate_stmt;
END LOOP;
END IF;
END IF;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
Refactored Function(s)
CREATE OR REPLACE FUNCTION execute_recreate_stmt_from_records(input_cursor refcursor) RETURNS integer AS $$
BEGIN
FOR table_record IN input_cursor LOOP
EXECUTE table_record.recreate_stmt;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION execute_drop_stmt_from_records(input_cursor refcursor) RETURNS integer AS $$
BEGIN
FOR table_record IN input_cursor LOOP
EXECUTE table_record.drop_stmt;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION drop_indexes_and_constraints(table_name_to_drop varchar) RETURNS integer AS $$
DECLARE
indexes_and_constraints CURSOR IS SELECT drop_stmt FROM table_indexes WHERE table_indexes.table_name = table_name_to_drop;
SELECT execute_drop_stmt_from_records(indexes_and_constraints);
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION drop_all_indexes_and_constraints() RETURNS integer AS $$
DECLARE
indexes_and_constraints CURSOR IS SELECT drop_stmt FROM table_indexes;
SELECT execute_drop_stmt_from_records(indexes_and_constraints);
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION recreate_indexes_and_constraints(table_name_to_recreate varchar) RETURNS integer AS $$
DECLARE
indexes_and_constraints CURSOR IS SELECT recreate_stmt FROM table_indexes WHERE table_indexes.table_name = table_name_to_recreate;
SELECT execute_recreate_stmt_from_records(indexes_and_constraints);
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION recreate_all_indexes_and_constraints() RETURNS integer AS $$
DECLARE
indexes_and_constraints CURSOR IS SELECT recreate_stmt FROM table_indexes;
SELECT execute_recreate_stmt_from_records(indexes_and_constraints);
$$ LANGUAGE plpgsql;
I believe the underlying problem with my refactor is that the helper functions, execute_recreate_stmt_from_records and execute_drop_stmt_from_records, are way too powerful to be publicly accessible, especially since Heroku (which hosts this DB) only allows one DB user. Of course, if there are other problems with the above refactor, feel free to point them out.
You can reach separation by moving "private" procedures into a new schema, limiting access to it. Then use a SECURITY DEFINER to allow calls to "private" functions.
Although, this will be hard to achieve if you are limited to a single user by your hosting service.
Example:
CREATE USER app_user;
CREATE USER private_user;
GRANT ALL ON DATABASE my_database TO app_user;
GRANT CONNECT, CREATE ON DATABASE my_database TO private_user;
-- With private_user:
CREATE SCHEMA private;
CREATE OR REPLACE FUNCTION private.test_func1()
RETURNS integer AS
$BODY$
BEGIN
RETURN 123;
END
$BODY$
LANGUAGE plpgsql STABLE
COST 100;
CREATE OR REPLACE FUNCTION public.my_function_1()
RETURNS integer AS
$BODY$
DECLARE
BEGIN
RETURN private.test_func1();
END
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;
-- With app_user:
SELECT private.test_func1(); -- ERROR: permission denied for schema private
SELECT my_function_1(); -- Returns 123

How to create a trigger that checks values?

I need help with my trigger. For example i have Query like this
INSERT INTO test(id_users,id_type,id_color) VALUES(1,3,4);
in my data base i have table with name: test
ghost, id, id_users, id_type, id_color
and i need before insert or update to check
Create trigger
Begin
select id from test where ghost = false and id_users = 26 and id_type = 3
if NO execute INSERT
if YEST exit with no action
END
How can i creat this trigger ?
There are two ways, depending on how you want to manage the problem.
If you wish to silence it, use a before trigger and return null:
create function ignore_invalid_row() returns trigger as $$
begin
if not exists(
select 1
from test
where not ghost
and id_users = new.id_users
and id_type = new.id_type
)
then
return null;
end if;
return new;
end;
$$ language plpgsql;
create trigger ignore_invalid_row_tg before insert on test
for each row execute procedure ignore_invalid_row();
If you wish to raise it, use a constraint trigger and raise an exception:
create function reject_invalid_row() returns trigger as $$
begin
if not exists(
select 1
from test
where not ghost
and id_users = new.id_users
and id_type = new.id_type
)
then
raise exception 'message';
end if;
return null;
end;
$$ language plpgsql;
create constraint trigger reject_invalid_row_tg after insert on test
for each row execute procedure reject_invalid_row();
http://www.postgresql.org/docs/current/static/sql-createtrigger.html
First, you need to create a trigger function and then the trigger, based on it:
CREATE OR REPLACE FUNCTION my_trigger_function() RETURNS TRIGGER AS $BODY$ BEGIN
IF EXISTS (SELECT id FROM test WHERE ghost = false AND id_users = 26 AND id_type = 3) THEN
return NEW;
ELSE
return NULL;
END IF; END; $BODY$ LANGUAGE 'plpgsql';
Then, you create trigger based on this function:
CREATE TRIGGER t_my_trigger BEFORE INSERT ON test FOR EACH ROW EXECUTE PROCEDURE my_trigger_function();
For more on triggers, see postgres docs.