From: | "Karl Nack" <karlnack(at)futurityinc(dot)com> |
---|---|
To: | "David Johnston" <polobo(at)yahoo(dot)com> |
Cc: | "Chris Travers" <chris(dot)travers(at)gmail(dot)com>, "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org> |
Subject: | Re: Implementing "thick"/"fat" databases |
Date: | 2011-07-23 23:08:21 |
Message-ID: | 1311462501.10482.2155141965@webmail.messagingengine.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
> > Now, if you are doing double-entry bookkeeping this doesn't provide
> > enough consistency, IMO. You can't check inside the function to
> > ensure that the transaction is balanced.
>
> One option to consider is restricting final tables but making staging
> tables available.
I would implement this using triggers.
First, add a boolean "is_balanced" column to the transaction table,
along with the following trigger:
create or replace function check_txn_balance()
returns trigger
language plpgsql
as $$
declare
_amt numeric;
begin
if 'UPDATE' = TG_OP and new.is_balanced then
return null;
end if;
select sum(amt)
into _amt
from line_item
where txn_id = new.id;
if _amt <> 0 then
raise exception 'unbalanced transaction';
end if;
update txn
set is_balanced = true
where id = new.id;
return null;
end;
$$;
create constraint trigger check_txn_balance
after insert or update on txn
deferrable initially deferred
for each row execute procedure check_txn_balance();
Then, whenever we add, remove, or update a line item, unbalance the
parent transaction, which triggers the balance check:
create or replace function unbalance_txn()
returns trigger
language plpgsql
as $$
begin
if 'UPDATE' = TG_OP then
if (new.txn_id, new.amt) = (old.txn_id, old.amt) then
return null;
end if;
end if;
if TG_OP in ('INSERT', 'UPDATE') then
update txn
set is_balanced = false
where (id, is_balanced) = (new.txn_id, true);
end if;
if TG_OP in ('DELETE', 'UPDATE') then
update txn
set is_balanced = false
where (id, is_balanced) = (old.txn_id, true);
end if;
return null;
end;
$$;
create trigger unbalance_txn
after insert or delete or update on line_item
for each row execute procedure unbalance_txn();
At least, this seems to be a fairly efficient and foolproof way to do it
to me.
Karl Nack
Futurity, Inc
5121 N Ravenswood Ave
Chicago, IL 60640
773-506-2007
From | Date | Subject | |
---|---|---|---|
Next Message | David Johnston | 2011-07-23 23:24:15 | Re: Implementing "thick"/"fat" databases |
Previous Message | Darren Duncan | 2011-07-23 22:58:12 | Re: Implementing "thick"/"fat" databases |