On Friday, January 25, 2019 at 9:42:37 AM UTC-8, Greg H wrote:
>
> Hi there
>
> I'd like to order the results from an UPDATE .. RETURNING statement 
> (sequel's .returning() method).
> Is this possible?
> My approach detailed below isn't working, so I'd appreciate some advice.
>
> Many thanks
> Greg
>
> --
>
> To order the results from an UPDATE .. RETURNING statement, I've followed 
> the suggestion from:
>
> https://stackoverflow.com/questions/25649976/update-returning-order-by-in-postgresql
>
> In short, assign the UPDATE .. RETURNING dataset to a Common Table 
> Expression, then sort that.
>
> So in sequel-land, use:
>
> https://www.rubydoc.info/github/jeremyevans/sequel/Sequel%2FDataset:returning
> as input to..
> https://www.rubydoc.info/github/jeremyevans/sequel/Sequel%2FDataset:with
>
> However, this doesn't seem to work, though using a .select() as input to 
> .with() does.
> From debugging, the main difference is that .returning() actually runs the 
> update and returns an array of hash-results, whilst .select() is a sequel 
> dataset (hasn't run yet)
>
> == Works (.select as input to .with) ==
>
> claimed_jobs = @db[:jobs].select(:id, :created_at, :status).where(id: 
> oldest_runnable_job_ids)
> ordered_claimed_jobs_data = @db[:claimed_jobs].with(:claimed_jobs, 
> claimed_jobs).order(Sequel.asc :created_at).all
>
> == Doesn't work (.returning as input to .with) ==
>
> claimed_jobs = @db[:jobs].returning(:id, :created_at, :status).where(id: 
> oldest_runnable_job_ids).update(status: 'ACTIVE')
> ordered_claimed_jobs_data = @db[:claimed_jobs].with(:claimed_jobs, 
> claimed_jobs).order(Sequel.asc :created_at).all
>
> The .with call errors with: NoMethodError: undefined method `opts' for 
> #<Array:0x000056172631f1f8>
>

The doesn't work example is because Dataset#update in the first line runs 
the UPDATE query and returns the number of rows updated. In the first line, 
switch:

  update(status: 'ACTIVE')

to:

  with_sql(:update_sql, status: 'ACTIVE')

Then the second line will work and produce the following SQL:

WITH "claimed_jobs" AS (
  UPDATE "jobs"
  SET "status" = 'ACTIVE'
  WHERE ("id" IN (1))
  RETURNING "id", "created_at", "status"
)
SELECT *
FROM "claimed_jobs"
ORDER BY "created_at" ASC

I'm guessing (but haven't tested) you can also use a subquery instead of a 
CTE:

  claimed_jobs.from_self.order(:created_at).all

which produces this SQL:

SELECT * FROM (
  UPDATE "jobs"
  SET "status" = 'ACTIVE'
  WHERE ("id" IN (1))
  RETURNING "id", "created_at", "status"
) AS "t1"
ORDER BY "created_at"

Thanks,
Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.

Reply via email to