Re: Volatile functions in WITH - Mailing list pgsql-sql
| From | Sergey Konoplev |
|---|---|
| Subject | Re: Volatile functions in WITH |
| Date | |
| Msg-id | CAL_0b1uWOn=UukdngytfgzP2ySHgz45qHtpxA5LwUXjjKkor0w@mail.gmail.com Whole thread |
| In response to | Volatile functions in WITH (Ben Morrow <ben@morrow.me.uk>) |
| Responses |
Re: Volatile functions in WITH
|
| List | pgsql-sql |
On Sat, Feb 16, 2013 at 11:58 PM, Ben Morrow <ben@morrow.me.uk> wrote:
> 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
Alternatively I suppose you can try this one:
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 ), "upd" AS ( UPDATE "item" SET "count" = e.count
FROM "exp" e WHERE e.nref IS NOT NULL AND ("basket", "nref") IS NOT DISTINCT FROM (e.basket, e.nref)
RETURNING "basket", "nref" ) "ins" AS ( INSERT INTO "item" ("basket", "ref", "count") SELECT e.basket,
e.nref,e.count FROM "exp" e LEFT JOIN "upd" u ON ("basket", "nref") IS NOT DISTINCT FROM (e.basket, e.nref)
WHERE e.nref IS NOT NULL AND (u.basket, u.nref) IS 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.)
In this regard I would like to listen to gugrus' opinion too.
EXPLAIN ANALYZE WITH t AS (SELECT random()) SELECT 1; QUERY PLAN
------------------------------------------------------------------------------------Result (cost=0.00..0.01 rows=1
width=0)(actual time=0.002..0.003
rows=1 loops=1)Total runtime: 0.063 ms
(2 rows)
EXPLAIN ANALYZE WITH t AS (SELECT random()) SELECT 1 from t; QUERY PLAN
--------------------------------------------------------------------------------------------CTE Scan on t
(cost=0.01..0.03rows=1 width=0) (actual
time=0.048..0.052 rows=1 loops=1) CTE t -> Result (cost=0.00..0.01 rows=1 width=0) (actual
time=0.038..0.039 rows=1 loops=1)Total runtime: 0.131 ms
(4 rows)
I couldn't manage to come to any solution except faking the reference
in the resulting query:
WITH t AS (SELECT random()) SELECT 1 UNION ALL (SELECT 1 FROM t LIMIT 0);
>
> 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
--
Sergey Konoplev
Database and Software Architect
http://www.linkedin.com/in/grayhemp
Phones:
USA +1 415 867 9984
Russia, Moscow +7 901 903 0499
Russia, Krasnodar +7 988 888 1979
Skype: gray-hemp
Jabber: gray.ru@gmail.com