post queries: fix handling of '~' operator.
Fix queries like `(~a ~b) (~c ~d)` being handled like `~a ~b ~c ~d`. Caused by trimming AND nodes from the tree before rewriting the '~' operator, which caused `~a` terms to be incorrectly lifted out of subexpressions.
This commit is contained in:
@@ -13,7 +13,7 @@ class PostQuery
|
||||
|
||||
# Return a new PostQuery with aliases replaced.
|
||||
def self.normalize(...)
|
||||
PostQuery.new(...).replace_aliases.trim
|
||||
PostQuery.new(...).replace_aliases.rewrite_opts.trim
|
||||
end
|
||||
|
||||
def initialize(search_or_ast, current_user: User.anonymous, tag_limit: nil, safe_mode: false, hide_deleted_posts: false)
|
||||
@@ -129,6 +129,11 @@ class PostQuery
|
||||
build(ast.trim)
|
||||
end
|
||||
|
||||
# Return a new PostQuery with the '~' operator replaced with OR clauses.
|
||||
def rewrite_opts
|
||||
build(ast.rewrite_opts)
|
||||
end
|
||||
|
||||
# Return a new PostQuery with aliases replaced.
|
||||
def replace_aliases
|
||||
return self if aliases.empty?
|
||||
|
||||
@@ -1311,6 +1311,40 @@ class PostQueryBuilderTest < ActiveSupport::TestCase
|
||||
assert_tag_match([], "-aaa id:>0")
|
||||
assert_tag_match([], "-a* rating:s")
|
||||
end
|
||||
|
||||
should "succeed for nested OR clauses" do
|
||||
post1 = create(:post, tag_string: "a c")
|
||||
post2 = create(:post, tag_string: "b d")
|
||||
post3 = create(:post, tag_string: "a")
|
||||
post4 = create(:post, tag_string: "d")
|
||||
|
||||
assert_tag_match([post3, post2, post1], "~a ~b")
|
||||
assert_tag_match([post3, post2, post1], "a or b")
|
||||
|
||||
assert_tag_match([post4, post2, post1], "~c ~d")
|
||||
assert_tag_match([post4, post2, post1], "c or d")
|
||||
|
||||
assert_tag_match([post2, post1], "(a or b) (c or d)")
|
||||
assert_tag_match([post2, post1], "(~a ~b) (~c ~d)")
|
||||
|
||||
assert_tag_match([post2, post1], "a c or b d")
|
||||
assert_tag_match([post2, post1], "(a c) or (b d)")
|
||||
assert_tag_match([post2, post1], "~(a c) or ~(b d)")
|
||||
end
|
||||
|
||||
should "succeed for metatags combined with OR clauses" do
|
||||
post1 = create(:post, rating: "s")
|
||||
post2 = create(:post, rating: "q")
|
||||
post3 = create(:post, rating: "e")
|
||||
|
||||
assert_tag_match([post2, post1], "~rating:s ~rating:q")
|
||||
assert_tag_match([post3, post2, post1], "~rating:s ~rating:q ~rating:e")
|
||||
|
||||
assert_tag_match([post2, post1], "rating:s or rating:q")
|
||||
assert_tag_match([post3, post2, post1], "rating:s or rating:q or rating:e")
|
||||
|
||||
assert_tag_match([post2, post1], "id:#{post1.id} or rating:q")
|
||||
end
|
||||
end
|
||||
|
||||
context "Parsing:" do
|
||||
|
||||
Reference in New Issue
Block a user