Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

atomically increment in PostgreSQL hstore like $inc in MongoDB

New pg hstore looks awesome

http://www.postgresql.org/docs/devel/static/hstore.html

but it seems do not support atomically increment like MongoDB?

db.mycoll.update({mykey: myval}, {my_counter: {$inc: 1}})

How to do this with PostgreSQL Hstore?

like image 400
est Avatar asked Mar 22 '23 18:03

est


1 Answers

MongoDB needs a $inc operator because:

  1. Atomic operations in MongoDB are difficult without specific low-level support.
  2. The interface isn't rich enough to express c = c + 1 without a special operator.

You just need to express c = c + 1 with hstores. This task is complicated a little because hstores use strings for both the keys and values and that leaves you with a mess of casting. I think you're stuck with something nasty like this:

update t
set h = h || hstore('my_counter', ((h -> 'my_counter')::integer + 1)::text)
where mykey = myval

The (h -> 'my_counter')::integer + 1 does the increment by extracting the value (h -> 'my_counter'), casting it to an integer, and adding one to it. Then you build a single element hstore with hstore('my_counter', ...) and an explicit ::text cast on the value to make sure PostgreSQL knows which function you want. Finally, you concatenate the new key-value onto the original hstore with h || hstore(...) to replace the old value.

If you don't want to use that somewhat nasty mess all the time then you could wrap it a simple function and say:

update t
set h = hstore_inc(h, 'my_counter', 1)
where ...

to hide the nastiness.

I'm sure there are other ways to do it (using the various to/from array functions perhaps) but the above should work.

like image 125
mu is too short Avatar answered Apr 06 '23 00:04

mu is too short