[DBIx-Class-Devel] UPDATE RETURNING

Peter Rabbitson rabbit+dbic at rabbit.us
Mon Jul 15 16:00:26 GMT 2013


On Mon, Jul 15, 2013 at 10:46:55AM -0500, fREW Schmidt wrote:
> On Mon, Jul 15, 2013 at 03:25:46PM +0000, Peter Rabbitson wrote:
> > On Mon, Jul 15, 2013 at 10:13:11AM -0500, fREW Schmidt wrote:
> > > I just found out about UPDATE RETURNING (and the various dialects
> > > thereof, of course) and I'm aching to use it in DBIC.  What do you
> > > guys think about something like this?
> > >
> > > my @rows = $rs->update({ .... }, { columns => $columns_spec })->all;
> >
> > What is the actual use-case here? I understand what the construct does,
> > I am not sure how it is useful in practice.
> >
> 
> At work we maintain a table of devices and when they last checked in to
> the server.  If they haven't checked in recently enough (aka timed
> out) we do a special action.  Currently the way it works is, we have a
> single update that inserts our PID into the row's status if it has
> timed out, and then we iterate over the rows with our PID in the
> status, doing the special action as we go.  With UPDATE RETURNING this
> becomes a single "select" as we can get back the rows (or just their
> id's) in a single statement.  Basically it increases atomicity. 

This is a very contrived use-case (I would simply solve it with batches 
wrapped in transactions), and I don't think it warrants a full blown 
chunk of the scrace API. You kind-of agree further down.

> FWIW
> I could see it being very useful for shadow, but only with SQL Server
> as SQL Server's dialect can give you the values before UPDATE (pg
> gives the values after exclusively)

It won't be - I actually need the stuff post-RDBMS-side update, not 
before. INSERT and UPDATE record the state *after* each corresponding 
operation, only DELETE records the state before (due to ability of 
RDBMS-side cascades to disappear my relationship data). Remember it's 
not the snapshots that are hard, it is keeping track of the proper link 
between snapshots.

> 
> > > It should be able to use select/as too, fwiw.
> >
> > I am not sure what this comment implies...
> 
> $rs->update(..., { select => ..., as => ... })

I may misremember, but I think you can only return stored values, no 
aggreegates/subselects.

> 
> > > The other obvious and safe use case is to add another thing to the column
> > > definitions so that when a user calls $row->update the row object can
> > > have it's guts automatically updated.
> >
> > This is quote separate and something that can be cleanly folded in (and
> > be emulated on lesser RDBMS) - see the current implementation of
> > retrieve_on_insert. I would not mind the column attribute to be extended
> > with a retrieve_on_update boolean.
> >
> 
> Alright, so maybe the TL;DR for now is, we build this for just rows
> for starters, making reasonably good support for it, and then if we
> make the API useful enough I could make either a helper or an
> update_returning method in core that can give me what I want.

Something like that.

> As for my "lazy" comment, imagine we supported the following:
> 
>    say $_->name for $rs->search({
>       id => {
>          -in => $rs->update_returning({
>             foo => 'bar'
>          }, {
>             columns => 'id', # or maybe better yet ->get_column('id')
>          })->as_query
>       }
>    })->all
> 
> So update_returning returns an unfetched resultset, just like search
> does.

I don't think many engines support this (may very well be Pg only, 
verify) - but afaik RETURNING does not yield to being treated as a 
subselect. That is its values are only available to be shoved in a 
cursor.




More information about the DBIx-Class-Devel mailing list