Received: from maia.hub.org (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id 7628565B2CC for ; Tue, 16 Mar 2010 17:17:35 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 99166-03 for ; Tue, 16 Mar 2010 20:17:24 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from relay.ptn-ipout02.plus.net (relay.ptn-ipout02.plus.net [212.159.7.36]) by mail.postgresql.org (Postfix) with ESMTP id A74FA65B2C6 for ; Tue, 16 Mar 2010 17:17:24 -0300 (ADT) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AvsEAFaEn0vUnw4U/2dsb2JhbACbBHO6GIR4BI5F Received: from pih-relay08.plus.net ([212.159.14.20]) by relay.ptn-ipout02.plus.net with ESMTP; 16 Mar 2010 20:17:23 +0000 Received: from [84.51.143.99] (helo=server3.office.archonet.com) by pih-relay08.plus.net with esmtp (Exim) id 1NrdCc-0003Ry-TV; Tue, 16 Mar 2010 20:17:23 +0000 Received: from [192.168.1.36] (dell36.office.archonet.com [192.168.1.36]) by server3.office.archonet.com (Postfix) with ESMTPA id 7A621274091; Tue, 16 Mar 2010 20:17:22 +0000 (GMT) Message-ID: <4B9FE752.4080709@archonet.com> Date: Tue, 16 Mar 2010 20:17:22 +0000 From: Richard Huxton User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9pre) Gecko/20100217 Lightning/1.0b1 Shredder/3.0.3pre MIME-Version: 1.0 To: Tony Cebzanov CC: pgsql-sql@postgresql.org Subject: Re: Avoiding cycles in a directed graph References: <4B9FDFDE.5030005@andrew.cmu.edu> In-Reply-To: <4B9FDFDE.5030005@andrew.cmu.edu> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Plusnet-Relay: 8a008f9892801b61ab204c0b59ebbb74 X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-2.599 tagged_above=-10 required=5 tests=BAYES_00=-2.599 X-Spam-Level: X-Archive-Number: 201003/111 X-Sequence-Number: 33818 On 16/03/10 19:45, Tony Cebzanov wrote: > I'm using the following table to represent an acyclic directed graph: [snip] > I see there is an example in the online docs for detecting cycles in > recursive queries, and I've adapted the example query to the table above: [snip] > That's great to avoid looping forever on queries, but what about > preventing anyone from inserting edges that would create cycles in the > first place? I reckon I'll need a trigger of some sort, but nothing > I've tried has enabled me to do the cycle check as part of the trigger > to avoid inserting an edge that would create a cycle. You've got the right idea. If you know that the table doesn't contain any cycles at the moment, then all the trigger has to do is: 1. Check "parent" <> "child" 2. Build the set of parents of "parent". 3. Check "child" isn't in that set. 4. If there is a cycle, raise an error (which will abort the insert or update) If you have a "before" trigger, then step 4 could return NULL rather than raise an error. That would just skip the insert. Also, step #1 could be done with a CHECK constraint which would be checked before your trigger gets run. -- Richard Huxton Archonet Ltd