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 Raw
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



pgsql-sql by date:

Previous
From: Bert
Date:
Subject: Re: query doesn't always follow 'correct' path..
Next
From: Ben Morrow
Date:
Subject: Re: Volatile functions in WITH