Question

I want to use a query like this in my rails app:

Series.where("dimensions @> 'a=>1, b=>2'::hstore")

Except that I need to use wildcards (or named params) in order not to introduce an SQL injection bug:

Series.where("dimensions @> '?=>?, ?=>?'::hstore", 'a', '1', 'b', '2')

The latter doesn't work however, because hstore doesn't expect the keys/values to be quoted with single quotes. Here's the error:

PG::SyntaxError: ERROR:  syntax error at or near "a"
LINE 1: ... "series".* FROM "series"  WHERE (dimensions @> ''a'=>'1', '...
                                                             ^
: SELECT "series".* FROM "series"  WHERE (dimensions @> ''a'=>'1', 'b'=>'2''::hstore)

What's a proper way to use wildcards with hstore?

Thanks!

Was it helpful?

Solution

There are other ways to construct an hstore than using a text-to-hstore cast:

  • hstore(text[]): construct an hstore from an array, which may be either a key/value array, or a two-dimensional array.
  • hstore(text[], text[]): construct an hstore from separate key and value arrays.
  • hstore(text, text): make single-item hstore.

So you can do these things:

hstore('k', 'v')                             -- "k"=>"v"
hstore(array['k1', 'k2'], array['v1', 'v2']) -- "k1"=>"v1", "k2"=>"v2"
hstore(array['k1', 'v1', 'k2', 'v2'])        -- "k1"=>"v1", "k2"=>"v2"
hstore(array[['k1', 'v1'], ['k2', 'v2']])    -- "k1"=>"v1", "k2"=>"v2"

Perhaps you'll more success with this:

Series.where('dimensions @> hstore(array[:k1, :v1, :k2, :v2])',
  :k1 => 'a', :v1 => '1',
  :k2 => 'b', :v2 => '2'
)

That version only has one level of quotes so AR shouldn't make a mess. I also switched to named placeholders along the way, more than a couple anonymous placeholders gets confusing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top