Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use element operator instead of contains for jsonb querying #159

Merged
merged 3 commits into from
Jan 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ def initialize(_attributes, options)

private

def contains_value(key, value, locale)
build_infix(:'@>',
def matches(key, value, locale)
build_infix(:'->',
build_infix(:'->', column, quote(locale)),
quote({ key => value }.to_json))
quote(key)).eq(quote(value.to_json))
end

def has_locale(key, locale)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class ActiveRecord::Hstore::QueryMethods < ActiveRecord::QueryMethods

private

def contains_value(key, value, locale)
def matches(key, value, locale)
build_infix(:'->', arel_table[key], quote(locale)).eq(quote(value.to_s))
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/mobility/backends/active_record/jsonb/query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class ActiveRecord::Jsonb::QueryMethods < ActiveRecord::QueryMethods

private

def contains_value(key, value, locale)
build_infix(:'@>', arel_table[key], quote({locale => value }.to_json))
def matches(key, value, locale)
build_infix(:'->', arel_table[key], quote(locale)).eq(quote(value.to_json))
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/mobility/backends/active_record/pg_query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module ActiveRecord
=begin

Defines query methods for Postgres backends. Including class must define a
single method, +contains_value+, which accepts a column, value and locale to
single method, +matches+, which accepts a column, value and locale to
match, and returns an Arel node.

This module avoids 99% duplication between hstore and jsonb backend querying
Expand Down Expand Up @@ -70,7 +70,7 @@ def create_where_query!(opts, keys)
Array.wrap(values).map { |value|
value.nil? ?
has_locale(key, locale).not :
contains_value(key, value, locale)
matches(key, value, locale)
}.inject(&:or)
}.inject(&:and)
end
Expand All @@ -87,14 +87,14 @@ def create_not_query!(opts, keys)
values = opts.delete(key)

Array.wrap(values).map { |value|
contains_value(key, value, locale).not
matches(key, value, locale).not
}.inject(has_locale(key, locale), &:and)
}.inject(&:and)
end

private

def contains_value(_key, _value, _locale)
def matches(_key, _value, _locale)
raise NotImplementedError
end

Expand Down
4 changes: 2 additions & 2 deletions lib/mobility/backends/sequel/container/query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ def initialize(attributes, options)

private

def contains_value(key, value, locale)
build_op(column_name)[locale].contains({ key.to_s => value }.to_json)
def matches(key, value, locale)
build_op(column_name)[locale][key.to_s] =~ value.to_json
end

def has_locale(key, locale)
Expand Down
2 changes: 1 addition & 1 deletion lib/mobility/backends/sequel/hstore/query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def initialize(attributes, _)

private

def contains_value(key, value, locale)
def matches(key, value, locale)
build_op(key).contains(locale => value.to_s)
end

Expand Down
4 changes: 2 additions & 2 deletions lib/mobility/backends/sequel/jsonb/query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def initialize(attributes, _)

private

def contains_value(key, value, locale)
build_op(key).contains({ locale => value }.to_json)
def matches(key, value, locale)
build_op(key)[locale] =~ value.to_json
end

def has_locale(key, locale)
Expand Down
10 changes: 5 additions & 5 deletions lib/mobility/backends/sequel/pg_query_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ module Sequel
Defines query methods for Postgres backends. Including class must define two
private methods:

- a private method +contains_value+ which takes a key (column name), value and
- a private method +matches+ which takes a key (column name), value and
locale and returns an SQL expression, and checks that the column has the
specified value in the specified locale
- a private method +has_locale+ which takes a key (column name) and locale, and
returns an SQL expression which checks that the column has a value in the
locale

(The +contains_value+ method is implemented slightly differently for hstore and
(The +matches+ method is implemented slightly differently for hstore and
jsonb columns.)

=end
Expand Down Expand Up @@ -66,13 +66,13 @@ def create_query_op(key, value, invert)
locale = Mobility.locale.to_s

if invert
has_locale(key, locale) & ~contains_value(key, value, locale)
has_locale(key, locale) & ~matches(key, value, locale)
else
value.nil? ? ~has_locale(key, locale) : contains_value(key, value, locale)
value.nil? ? ~has_locale(key, locale) : matches(key, value, locale)
end
end

def contains_value(_key, _value, _locale)
def matches(_key, _value, _locale)
raise NotImplementedError
end

Expand Down
6 changes: 4 additions & 2 deletions spec/mobility/backends/active_record/container_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
expect(post.title).to eq(value)
post.save

post = ContainerPost.first
post = ContainerPost.last
expect(post.title).to eq(value)
end

Expand All @@ -56,7 +56,9 @@
end

it_behaves_like "container translated value", :integer, 1
it_behaves_like "container translated value", :hash, { "a" => "b" }
it_behaves_like "container translated value", :hash, { "a" => "b" } do
before { ContainerPost.create(title: { "a" => "b", "c" => "d" }) }
end
it_behaves_like "container translated value", :array, [1, "a", nil]
end
end
Expand Down
6 changes: 4 additions & 2 deletions spec/mobility/backends/active_record/jsonb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
expect(post.title).to eq(value)
post.save

post = JsonbPost.first
post = JsonbPost.last
expect(post.title).to eq(value)
end

Expand All @@ -57,7 +57,9 @@
end

it_behaves_like "jsonb translated value", :integer, 1
it_behaves_like "jsonb translated value", :hash, { "a" => "b" }
it_behaves_like "jsonb translated value", :hash, { "a" => "b" } do
before { JsonbPost.create(title: { "a" => "b", "c" => "d" }) }
end
it_behaves_like "jsonb translated value", :array, [1, "a", nil]
end
end
Expand Down
6 changes: 4 additions & 2 deletions spec/mobility/backends/sequel/container_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
expect(post.title).to eq(value)
post.save

post = ContainerPost.first
post = ContainerPost.last
expect(post.title).to eq(value)
end

Expand All @@ -54,7 +54,9 @@
end

it_behaves_like "jsonb translated value", :integer, 1
it_behaves_like "jsonb translated value", :hash, { "a" => "b" }
it_behaves_like "jsonb translated value", :hash, { "a" => "b" } do
before { ContainerPost.create(title: { "a" => "b", "c" => "d" }) }
end
it_behaves_like "jsonb translated value", :array, [1, "a", nil]
end
end
Expand Down
6 changes: 4 additions & 2 deletions spec/mobility/backends/sequel/jsonb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
expect(post.title).to eq(value)
post.save

post = JsonbPost.first
post = JsonbPost.last
expect(post.title).to eq(value)
end

Expand All @@ -55,7 +55,9 @@
end

it_behaves_like "jsonb translated value", :integer, 1
it_behaves_like "jsonb translated value", :hash, { "a" => "b" }
it_behaves_like "jsonb translated value", :hash, { "a" => "b" } do
before { JsonbPost.create(title: { "a" => "b", "c" => "d" }) }
end
it_behaves_like "jsonb translated value", :array, [1, "a", nil]
end
end
Expand Down