X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (neptune.hub.org [200.46.204.2]) by svr1.postgresql.org (Postfix) with ESMTP id 43854D1B454 for ; Sun, 4 Jan 2004 17:49:21 +0000 (GMT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (neptune.hub.org [200.46.204.2]) (amavisd-new, port 10024) with ESMTP id 01074-03 for ; Sun, 4 Jan 2004 13:48:31 -0400 (AST) Received: from sss.pgh.pa.us (unknown [192.204.191.242]) by svr1.postgresql.org (Postfix) with ESMTP id 9399FD1B45F for ; Sun, 4 Jan 2004 13:48:30 -0400 (AST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss.pgh.pa.us (8.12.10/8.12.10) with ESMTP id i04HmQ19021120; Sun, 4 Jan 2004 12:48:26 -0500 (EST) To: Tatsuo Ishii Cc: pgsql-sql@postgresql.org, Jan Wieck Subject: Re: DO INSTEAD in rule In-reply-to: <20040104.225115.71101762.t-ishii@sra.co.jp> References: <20040104.225115.71101762.t-ishii@sra.co.jp> Comments: In-reply-to Tatsuo Ishii message dated "Sun, 04 Jan 2004 22:51:15 +0900" Date: Sun, 04 Jan 2004 12:48:26 -0500 Message-ID: <21119.1073238506@sss.pgh.pa.us> From: Tom Lane X-Virus-Scanned: by amavisd-new at postgresql.org X-Archive-Number: 200401/17 X-Sequence-Number: 16410 Tatsuo Ishii writes: > In the last SELECT I exepcted j = 0, rather than j = 1 since I use DO > INSTEAD in the rule and the default value for j is 0. Am I missing > something? > CREATE rule t1_ins AS ON INSERT TO t1 > WHERE (EXISTS (SELECT 1 FROM t1 > WHERE i = new.i)) > DO INSTEAD UPDATE t1 SET j = j + 1 > WHERE i = new.i; Hm. The problem is that the rule query runs after the INSERT and so it sees the inserted row as something to update. The logic is essentially if (not (EXISTS ...)) then do the INSERT; if (EXISTS ...) then do the UPDATE; and the second command sees the inserted row as existing, so it updates it. Without an if-then-else kind of control structure for the executor, I'm not sure we can do better. (Even with one, I'm not sure how to handle cases where the INSERT inserts multiple rows.) Consider using a trigger instead of a rule to do this. Or, accept that the UPDATE will happen unconditionally, and start J off one less than it should be. Note that either solution will have race conditions if multiple processes try to insert the same row at the same time. There are discussions in the archives about how to avoid that, but I'm not sure anyone found a really satisfactory answer that didn't involve an unpleasant amount of locking. regards, tom lane