search: fix bug with negated user metatags.

Bug: searching for "filetype:jpg -user:evazion" would negate the
filetype:jpg metatag too. This was because the -user:<name> metatag was
negating the entire cumulative relation instead of just the user:<name>
clause.
This commit is contained in:
evazion
2020-04-17 00:29:09 -05:00
parent 99e7e359af
commit c1ce5024e4
2 changed files with 55 additions and 51 deletions

View File

@@ -123,30 +123,39 @@ class PostQueryBuilder
array.map(&:to_escaped_for_tsquery) array.map(&:to_escaped_for_tsquery)
end end
def add_user_relation(field, username, relation) def user_matches(field, username)
if username == "any" if username == "any"
relation.where.not(field => nil) Post.where.not(field => nil)
elsif username == "none" elsif username == "none"
relation.where(field => nil) Post.where(field => nil)
else else
relation.where(field => User.name_matches(username)) Post.where(field => User.name_matches(username))
end end
end end
def add_user_subquery_relation(table, username, relation, field: :creator, &block) def user_subquery_matches(subquery, username, field: :creator, &block)
subquery = table.where("post_id = posts.id").select(1) subquery = subquery.where("post_id = posts.id").select(1)
if username == "any" if username == "any"
relation.where("EXISTS (#{subquery.to_sql})") Post.where("EXISTS (#{subquery.to_sql})")
elsif username == "none" elsif username == "none"
relation.where("NOT EXISTS (#{subquery.to_sql})") Post.where("NOT EXISTS (#{subquery.to_sql})")
elsif block.nil? elsif block.nil?
subquery = subquery.where(field => User.name_matches(username)) subquery = subquery.where(field => User.name_matches(username))
relation.where("EXISTS (#{subquery.to_sql})") Post.where("EXISTS (#{subquery.to_sql})")
else else
subquery = subquery.merge(block.call(username)) subquery = subquery.merge(block.call(username))
return relation.none if subquery.to_sql.blank? return Post.none if subquery.to_sql.blank?
relation.where("EXISTS (#{subquery.to_sql})") Post.where("EXISTS (#{subquery.to_sql})")
end
end
def flagger_matches(username)
flags = PostFlag.unscoped.category_matches("normal")
user_subquery_matches(flags, username) do |username|
flagger = User.find_by_name(username)
PostFlag.unscoped.creator_matches(flagger, CurrentUser.user)
end end
end end
@@ -375,19 +384,19 @@ class PostQueryBuilder
end end
q[:user_neg].to_a.each do |username| q[:user_neg].to_a.each do |username|
relation = add_user_relation(:uploader, username, relation).negate relation = relation.merge(user_matches(:uploader, username).negate)
end end
q[:user].to_a.each do |username| q[:user].to_a.each do |username|
relation = add_user_relation(:uploader, username, relation) relation = relation.merge(user_matches(:uploader, username))
end end
q[:approver_neg].to_a.each do |username| q[:approver_neg].to_a.each do |username|
relation = add_user_relation(:approver, username, relation).negate relation = relation.merge(user_matches(:approver, username).negate)
end end
q[:approver].to_a.each do |username| q[:approver].to_a.each do |username|
relation = add_user_relation(:approver, username, relation) relation = relation.merge(user_matches(:approver, username))
end end
if q[:disapproved] if q[:disapproved]
@@ -414,58 +423,52 @@ class PostQueryBuilder
end end
end end
q[:flagger_neg].to_a.each do |flagger| q[:flagger_neg].to_a.each do |username|
relation = add_user_subquery_relation(PostFlag.unscoped.category_matches("normal"), flagger, relation) do |username| relation = relation.merge(flagger_matches(username).negate)
flagger = User.find_by_name(username)
PostFlag.unscoped.creator_matches(flagger, CurrentUser.user)
end.negate
end end
q[:flagger].to_a.each do |flagger| q[:flagger].to_a.each do |username|
relation = add_user_subquery_relation(PostFlag.unscoped.category_matches("normal"), flagger, relation) do |username| relation = relation.merge(flagger_matches(username))
flagger = User.find_by_name(username)
PostFlag.unscoped.creator_matches(flagger, CurrentUser.user)
end
end end
q[:appealer_neg].to_a.each do |appealer| q[:appealer_neg].to_a.each do |username|
relation = add_user_subquery_relation(PostAppeal.unscoped, appealer, relation).negate relation = relation.merge(user_subquery_matches(PostAppeal.unscoped, username).negate)
end end
q[:appealer].to_a.each do |appealer| q[:appealer].to_a.each do |username|
relation = add_user_subquery_relation(PostAppeal.unscoped, appealer, relation) relation = relation.merge(user_subquery_matches(PostAppeal.unscoped, username))
end end
q[:commenter_neg].to_a.each do |commenter| q[:commenter_neg].to_a.each do |username|
relation = add_user_subquery_relation(Comment.unscoped, commenter, relation).negate relation = relation.merge(user_subquery_matches(Comment.unscoped, username).negate)
end end
q[:commenter].to_a.each do |commenter| q[:commenter].to_a.each do |username|
relation = add_user_subquery_relation(Comment.unscoped, commenter, relation) relation = relation.merge(user_subquery_matches(Comment.unscoped, username))
end end
q[:noter_neg].to_a.each do |noter| q[:noter_neg].to_a.each do |username|
relation = add_user_subquery_relation(NoteVersion.unscoped.where(version: 1), noter, relation, field: :updater).negate relation = relation.merge(user_subquery_matches(NoteVersion.unscoped.where(version: 1), username, field: :updater).negate)
end end
q[:noter].to_a.each do |noter| q[:noter].to_a.each do |username|
relation = add_user_subquery_relation(NoteVersion.unscoped.where(version: 1), noter, relation, field: :updater) relation = relation.merge(user_subquery_matches(NoteVersion.unscoped.where(version: 1), username, field: :updater))
end end
q[:note_updater_neg].to_a.each do |note_updater| q[:note_updater_neg].to_a.each do |username|
relation = add_user_subquery_relation(NoteVersion.unscoped, note_updater, relation, field: :updater).negate relation = relation.merge(user_subquery_matches(NoteVersion.unscoped, username, field: :updater).negate)
end end
q[:note_updater].to_a.each do |note_updater| q[:note_updater].to_a.each do |username|
relation = add_user_subquery_relation(NoteVersion.unscoped, note_updater, relation, field: :updater) relation = relation.merge(user_subquery_matches(NoteVersion.unscoped, username, field: :updater))
end end
q[:commentary_updater_neg].to_a.each do |username| q[:commentary_updater_neg].to_a.each do |username|
relation = add_user_subquery_relation(ArtistCommentaryVersion.unscoped, username, relation, field: :updater).negate relation = relation.merge(user_subquery_matches(ArtistCommentaryVersion.unscoped, username, field: :updater).negate)
end end
q[:commentary_updater].to_a.each do |username| q[:commentary_updater].to_a.each do |username|
relation = add_user_subquery_relation(ArtistCommentaryVersion.unscoped, username, relation, field: :updater) relation = relation.merge(user_subquery_matches(ArtistCommentaryVersion.unscoped, username, field: :updater))
end end
if q[:post_id_negated] if q[:post_id_negated]
@@ -552,20 +555,20 @@ class PostQueryBuilder
relation = relation.where(id: favgroup.select("unnest(post_ids)")) relation = relation.where(id: favgroup.select("unnest(post_ids)"))
end end
q[:upvoter].to_a.each do |upvoter| q[:upvoter].to_a.each do |username|
relation = add_user_subquery_relation(PostVote.positive.visible(CurrentUser.user), upvoter, relation, field: :user) relation = relation.merge(user_subquery_matches(PostVote.positive.visible(CurrentUser.user), username, field: :user))
end end
q[:upvoter_neg].to_a.each do |upvoter| q[:upvoter_neg].to_a.each do |username|
relation = add_user_subquery_relation(PostVote.positive.visible(CurrentUser.user), upvoter, relation, field: :user).negate relation = relation.merge(user_subquery_matches(PostVote.positive.visible(CurrentUser.user), username, field: :user).negate)
end end
q[:downvoter].to_a.each do |downvoter| q[:downvoter].to_a.each do |username|
relation = add_user_subquery_relation(PostVote.negative.visible(CurrentUser.user), downvoter, relation, field: :user) relation = relation.merge(user_subquery_matches(PostVote.negative.visible(CurrentUser.user), username, field: :user))
end end
q[:downvoter_neg].to_a.each do |downvoter| q[:downvoter_neg].to_a.each do |username|
relation = add_user_subquery_relation(PostVote.negative.visible(CurrentUser.user), downvoter, relation, field: :user).negate relation = relation.merge(user_subquery_matches(PostVote.negative.visible(CurrentUser.user), username, field: :user).negate)
end end
q[:fav_neg].to_a.each do |username| q[:fav_neg].to_a.each do |username|

View File

@@ -2141,6 +2141,7 @@ class PostTest < ActiveSupport::TestCase
assert_tag_match([posts[0]], "user:#{users[0].name}") assert_tag_match([posts[0]], "user:#{users[0].name}")
assert_tag_match([posts[1]], "-user:#{users[0].name}") assert_tag_match([posts[1]], "-user:#{users[0].name}")
assert_tag_match([posts[1]], "filetype:jpg -user:#{users[0].name}")
end end
should "return posts for the approver:<name> metatag" do should "return posts for the approver:<name> metatag" do