Re: [GENERAL] Order of Update - Second Try

2006-03-21 Thread Geoffrey

Terry Lee Tucker wrote:

Hello List:

I posted a question over the weekend regarding this issue but I failed to 
communicate effectively what the problem is. I was weary :o[  Let me try 
again.


I have a plpgsql function which makes updates to a set of records across two 
tables in a One to Many relationship hereinafter referred to as parent and 
child.  The parent record contains two important sets of information that 
is relative to this process. The first is data that links the children to the 
parent. The second is data that links the parent to the to a third table that 
we will call totals. The update to the totals table is accomplished by the 
execution of a trigger that is fired as a result of updating the child 
records. The function updates the child records in a loop and then, at the 
bottom of the function, the parent table is updated, setting to null the 
values that link it to the totals table. The problem is that the update to 
the parent table is occurring first; then, the updates to the child records 
are occurring. 


I'm curious about this issue.  How is this possible?  I caught the 
previous posting, but didn't see any responses.  Is there anyway to deal 
with this issue.  I know I've got code that takes a similar approach and 
I'm now concerned that I'm going to trash my database.


Anyone?

--
Until later, Geoffrey

---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


Re: [GENERAL] Order of Update - Second Try

2006-03-21 Thread Martijn van Oosterhout
On Tue, Mar 21, 2006 at 06:56:23AM -0500, Terry Lee Tucker wrote:
 Hello List:
 
 I posted a question over the weekend regarding this issue but I failed to 
 communicate effectively what the problem is. I was weary :o[  Let me try 
 again.

I think one of the reasons why you're not getting any responses is that
the problem is complicated but you have not provided a complete
example. You don't for example say how the trigger is defined
(BEFORE|AFTER) (ROW|STATEMENT) DEFERRED yes/no? If you really want an
answer you're going to need to provide a complete example people can
run on their own systems.

have a nice day,
-- 
Martijn van Oosterhout   kleptog@svana.org   http://svana.org/kleptog/
 Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
 tool for doing 5% of the work and then sitting around waiting for someone
 else to do the other 95% so you can sue them.


signature.asc
Description: Digital signature


[GENERAL] Order of Update - Second Try

2006-03-21 Thread Terry Lee Tucker
Hello List:

I posted a question over the weekend regarding this issue but I failed to 
communicate effectively what the problem is. I was weary :o[  Let me try 
again.

I have a plpgsql function which makes updates to a set of records across two 
tables in a One to Many relationship hereinafter referred to as parent and 
child.  The parent record contains two important sets of information that 
is relative to this process. The first is data that links the children to the 
parent. The second is data that links the parent to the to a third table that 
we will call totals. The update to the totals table is accomplished by the 
execution of a trigger that is fired as a result of updating the child 
records. The function updates the child records in a loop and then, at the 
bottom of the function, the parent table is updated, setting to null the 
values that link it to the totals table. The problem is that the update to 
the parent table is occurring first; then, the updates to the child records 
are occurring. This is causing the totals table NOT to be updated due to the 
fact that the information needed by the trigger to find that parent has 
already been removed. I have proved that the above is happening by placing 
various RAISE NOTICE messages in triggers on the tables involved.

I can work around this by splitting the update into two transactions but I 
would like to understand why this is happening. I would like to recognize 
what circumstances might cause this to happen. In all my work with 
PostgreSQL, so far, I haven't seen this kind of behavior. I have tried to 
represent the table relationship below. Also, I point out that batch and 
chkno are the two elements of a UNIQUE index on the parent table. Is this the 
reason for the behavior?

parent
--
order_num, batch, chkno
batch and chkno are set to null at the bottom of the function.

child
  ---
  order_num, apply amount
  apply amount is what is updated on the child.

   Totals Table
   -
   batch, chkno, [...], [...]

rnd=# select version();
   version
--
 PostgreSQL 7.4.6 on i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.2.3 
20030502 (Red Hat Linux 3.2.3-49)
(1 row)

TIA
-- 
Quote: 65
A vote is like a rifle: its usefulness depends upon the character
 of the user.

 --Theodore Roosevelt

 Work: 1-336-372-6812
 Cell: 1-336-363-4719
email: [EMAIL PROTECTED]

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [GENERAL] Order of Update - Second Try

2006-03-21 Thread Terry Lee Tucker
Thanks for the response. I'm working on a simplified example now. It will take 
a little time to set it up.  I will post all the code for creating the much 
simplified tables and trigger.

Again, thanks for the response...

On Tuesday 21 March 2006 08:15 am, Martijn van Oosterhout saith:
 On Tue, Mar 21, 2006 at 06:56:23AM -0500, Terry Lee Tucker wrote:
  Hello List:
 
  I posted a question over the weekend regarding this issue but I failed to
  communicate effectively what the problem is. I was weary :o[  Let me try
  again.

 I think one of the reasons why you're not getting any responses is that
 the problem is complicated but you have not provided a complete
 example. You don't for example say how the trigger is defined
 (BEFORE|AFTER) (ROW|STATEMENT) DEFERRED yes/no? If you really want an
 answer you're going to need to provide a complete example people can
 run on their own systems.

 have a nice day,

-- 
Quote: 39
Posterity -- you will never know how much it has cost my generation
 to preserve your freedom. I hope you will make good use of it.

 --John Quincy Adams

 Work: 1-336-372-6812
 Cell: 1-336-363-4719
email: [EMAIL PROTECTED]

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: [GENERAL] Order of Update - Second Try

2006-03-21 Thread Terry Lee Tucker
Ok, find attached a script called test.sql that will create three tables 
called parent, child, and totals. It will create a simple AFTER UPDATE 
trigger on child and a BEFORE trigger on parent simply to show that the 
values of batch and chkno are set to NULL right in the beginning. Just load 
the thing in with the \i command. There is a function created called 
myfunc(int). Simply do: SELECT myfunc(99); to see what happens. After you 
execute the function, you will find that parent.total is zero, 
child.apply_amt for each record is zero, but totals is still set to 1500. It 
should be 1000.

Version info:
rnd=# select version();
   version
--
 PostgreSQL 7.4.6 on i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.2.3 
20030502 (Red Hat Linux 3.2.3-49)
(1 row)

Any insight is appreciated.
TIA

On Tuesday 21 March 2006 09:11 am, Terry Lee Tucker saith:
 Thanks for the response. I'm working on a simplified example now. It will
 take a little time to set it up.  I will post all the code for creating the
 much simplified tables and trigger.

 Again, thanks for the response...

 On Tuesday 21 March 2006 08:15 am, Martijn van Oosterhout saith:
  On Tue, Mar 21, 2006 at 06:56:23AM -0500, Terry Lee Tucker wrote:
   Hello List:
  
   I posted a question over the weekend regarding this issue but I failed
   to communicate effectively what the problem is. I was weary :o[  Let me
   try again.
 
  I think one of the reasons why you're not getting any responses is that
  the problem is complicated but you have not provided a complete
  example. You don't for example say how the trigger is defined
  (BEFORE|AFTER) (ROW|STATEMENT) DEFERRED yes/no? If you really want an
  answer you're going to need to provide a complete example people can
  run on their own systems.
 
  have a nice day,

 --
 Quote: 39
 Posterity -- you will never know how much it has cost my generation
  to preserve your freedom. I hope you will make good use of it.

  --John Quincy Adams

  Work: 1-336-372-6812
  Cell: 1-336-363-4719
 email: [EMAIL PROTECTED]

 ---(end of broadcast)---
 TIP 6: explain analyze is your friend
CREATE TABLE parent (
order_num   INT,
batch   INT,
chkno   VARCHAR,
total   INT
) WITHOUT OIDS;
CREATE INDEX batch_chkno ON parent (batch, chkno);

CREATE TABLE child (
recid   INT,
order_num   INT,
apply_amt   INT
) WITHOUT OIDS;

CREATE TABLE totals (
batch   INT,
chkno   VARCHAR,
amount  INT,
UNIQUE (batch, chkno)
) WITHOUT OIDS;


CREATE OR REPLACE FUNCTION parent_func () RETURNS TRIGGER AS '
DECLARE
BEGIN
IF TG_OP = ''UPDATE'' THEN
RAISE NOTICE ''%: batch: %  chkno: %'', TG_NAME, new.batch,
new.chkno;
END IF;

RETURN NEW;
END;
' LANGUAGE plpgsql;

CREATE TRIGGER parent_preupd BEFORE INSERT OR UPDATE ON parent
FOR EACH ROW EXECUTE PROCEDURE parent_func ();

CREATE OR REPLACE FUNCTION child_func () RETURNS TRIGGER AS '
DECLARE
parentRec   RECORD; -- parent record buffer
BEGIN
IF TG_OP = ''UPDATE'' THEN
/* find the parent record. */
SELECT INTO parentRec batch, chkno FROM parent
WHERE order_num = new.order_num;

RAISE NOTICE ''%: parentRec.batch: %  parentRec.chkno: %'',
TG_NAME, parentRec.batch, parentRec.chkno;

/* update the parent */
UPDATE parent SET total = total - old.apply_amt
WHERE order_num = new.order_num;
/* update totals */
UPDATE totals SET amount = amount - old.apply_amt
WHERE batch = parentRec.batch
AND chkno = parentRec.chkno;
END IF;

RETURN NEW;
END;
' LANGUAGE plpgsql;

CREATE TRIGGER child_write AFTER INSERT OR UPDATE ON child
FOR EACH ROW EXECUTE PROCEDURE child_func ();

CREATE OR REPLACE FUNCTION myfunc (integer) RETURNS void AS '
DECLARE
tripALIAS FOR $1;   -- order_num
childRecRECORD;
BEGIN
FOR childRec IN SELECT * FROM child
WHERE order_num = trip
LOOP
UPDATE child SET apply_amt = 0
WHERE recid = childRec.recid;
END LOOP;

UPDATE parent SET batch = NULL, chkno = NULL
WHERE order_num = trip;

RETURN;
END;
' LANGUAGE plpgsql;

/* Insert data. */
INSERT INTO totals (batch, chkno, amount) VALUES (100, 'BR-549', 1500);
INSERT INTO parent (order_num, batch, chkno, total) VALUES (99, 100,
'BR-549', 500);
INSERT INTO child (recid, order_num, apply_amt) VALUES (1, 99, 100);
INSERT INTO child (recid, order_num, apply_amt) VALUES (2, 99, 100);
INSERT INTO child (recid, order_num, apply_amt) VALUES (3, 99, 100);
INSERT INTO child (recid, order_num, apply_amt) VALUES (4, 99, 100);
INSERT INTO child (recid, order_num, 

Re: [GENERAL] Order of Update - Second Try

2006-03-21 Thread Stephan Szabo

 Ok, find attached a script called test.sql that will create three tables
 called parent, child, and totals. It will create a simple AFTER UPDATE
 trigger on child and a BEFORE trigger on parent simply to show that the
 values of batch and chkno are set to NULL right in the beginning. Just load
 the thing in with the \i command. There is a function created called
 myfunc(int). Simply do: SELECT myfunc(99); to see what happens. After you
 execute the function, you will find that parent.total is zero,
 child.apply_amt for each record is zero, but totals is still set to 1500. It
 should be 1000.

 Version info:
 rnd=# select version();
version
 --
  PostgreSQL 7.4.6 on i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.2.3
 20030502 (Red Hat Linux 3.2.3-49)
 (1 row)

 Any insight is appreciated.

I think in 8.0 or later it'd do what you want, however IIRC in 7.4 the
after triggers are delayed until after the full execution of the function
myfunc (ie, at the end of the outer statement).

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: [GENERAL] Order of Update - Second Try

2006-03-21 Thread Terry Lee Tucker
Stephan,

Thanks for the reply. We will be upgrading to version 8.x in the third quarter 
of the year. As I said, I have a workaround. I just wanted to know why it was 
behaving that way and you provided that. Thanks for the help.

On Tuesday 21 March 2006 11:36 am, Stephan Szabo saith:
  Ok, find attached a script called test.sql that will create three tables
  called parent, child, and totals. It will create a simple AFTER UPDATE
  trigger on child and a BEFORE trigger on parent simply to show that the
  values of batch and chkno are set to NULL right in the beginning. Just
  load the thing in with the \i command. There is a function created called
  myfunc(int). Simply do: SELECT myfunc(99); to see what happens. After you
  execute the function, you will find that parent.total is zero,
  child.apply_amt for each record is zero, but totals is still set to 1500.
  It should be 1000.
 
  Version info:
  rnd=# select version();
 version
  -
 - PostgreSQL 7.4.6 on
  i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.2.3 20030502 (Red Hat
  Linux 3.2.3-49)
  (1 row)
 
  Any insight is appreciated.

 I think in 8.0 or later it'd do what you want, however IIRC in 7.4 the
 after triggers are delayed until after the full execution of the function
 myfunc (ie, at the end of the outer statement).

 ---(end of broadcast)---
 TIP 1: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly

-- 
Quote: 71
When the Lord calls me home, whenever that may be, I will leave with
 the greatest love for this country of ours and eternal optimism for
 its future. I now begin the journey that will lead me into the sunset
 of my life. I know that for America there will always be a bright dawn
 ahead.

 --Ronald Reagan

 Work: 1-336-372-6812
 Cell: 1-336-363-4719
email: [EMAIL PROTECTED]

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster