Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.72) (envelope-from ) id 1U6z9V-0003eG-H4 for pgsql-sql@arkaria.postgresql.org; Sun, 17 Feb 2013 07:59:13 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.72) (envelope-from ) id 1U6z9U-0005bT-IP for pgsql-sql@arkaria.postgresql.org; Sun, 17 Feb 2013 07:59:12 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtp (Exim 4.72) (envelope-from ) id 1U6z9S-0005bL-IC for pgsql-sql@postgresql.org; Sun, 17 Feb 2013 07:59:10 +0000 Received: from isis.morrow.me.uk ([204.109.63.142]) by magus.postgresql.org with esmtp (Exim 4.72) (envelope-from ) id 1U6z9N-0004np-Ax for pgsql-sql@postgresql.org; Sun, 17 Feb 2013 07:59:09 +0000 Received: from anubis.morrow.me.uk (host109-150-212-220.range109-150.btcentralplus.com [109.150.212.220]) (Authenticated sender: mauzo) by isis.morrow.me.uk (Postfix) with ESMTPSA id 97BBB450C2 for ; Sun, 17 Feb 2013 07:59:02 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.7.4 isis.morrow.me.uk 97BBB450C2 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=morrow.me.uk; s=dkim201101; t=1361087942; bh=ciGdP7yV0zIxBSAGgBbhZA5AeglXMDnwq/CHSp2lMIg=; h=Date:From:To:Subject; b=l1MScZluHtkV3fDbX5LNb1XI9omVyuBUTEwp6sv+k4XnkWsT0X231NU1qwCmLRlmX l3j3wTWyhUgnOw7hZmmfmoCf1iHHENKxZEp5ifW+zTwqIIgJeeJanhieqDuZb2/fgv a1yMZZ2WgDvYy9sNbz16xIoOGcAXpEQOq/Ycc7Dg= X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.97.6 at isis.morrow.me.uk Received: by anubis.morrow.me.uk (Postfix, from userid 5001) id BDA08937B; Sun, 17 Feb 2013 07:58:59 +0000 (GMT) Date: Sun, 17 Feb 2013 07:58:59 +0000 From: Ben Morrow To: pgsql-sql@postgresql.org Subject: Volatile functions in WITH Message-ID: <20130217075859.GE8029@anubis.morrow.me.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Pg-Spam-Score: -2.6 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-sql Precedence: bulk Sender: pgsql-sql-owner@postgresql.org Suppose I run the following query: WITH "exp" AS ( DELETE FROM "item" i USING "item_expired" e WHERE e.oref = i.ref AND i.basket = $1 RETURNING i.basket, e.oref, e.nref, i.count, e.msg ), "subst" AS ( INSERT INTO "item" ("basket", "ref", "count") SELECT e.basket, e.nref, e.count FROM "exp" e WHERE e.nref IS NOT NULL ) SELECT DISTINCT e.msg FROM "exp" e This is a very convenient and somewhat more flexible alternative to INSERT... DELETE RETURNING (which doesn't work). However, the "item" table has a unique constraint on (basket, ref), so sometimes I need to update instead of insert; to handle this I have a VOLATILE function, add_item. Unfortunately, if I call it the obvious way WITH "exp" AS ( -- as before ), "subst" AS ( SELECT add_item(e.basket, e.nref, e.count) FROM "exp" e WHERE e.nref IS NOT NULL ) SELECT DISTINCT e.msg FROM "exp" e then the planner sees that the results of "subst" are not used, and doesn't include it in the query plan at all. Is there any way I can tell WITH that add_item is actually a data- modifying statement? Adding FOR UPDATE doesn't seem to help (I didn't really expect it would.) Alternatively, are either of these safe (that is, are they guaranteed to call the function once for every row returned by "exp", even if the DISTINCT ends up eliminating some of those rows)? WITH "exp" AS ( -- as before ), "subst" AS ( -- SELECT add_item(...) as before ) SELECT DISTINCT e.msg FROM "exp" e LEFT JOIN "subst" s ON FALSE WITH "exp" AS ( -- as before ) SELECT DISTINCT s.msg FROM ( SELECT e.msg, CASE WHEN e.nref IS NULL THEN NULL ELSE add_item(e.basket, e.nref, e.count) END "subst" ) s I don't like the second alternative much, but I could live with it if I had to. Ben -- Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql