From ddfa6b87d18a3adc80127b14794016167b846ee1 Mon Sep 17 00:00:00 2001 From: Justin DiRose Date: Tue, 13 Oct 2020 17:15:05 -0500 Subject: [PATCH 1/2] FIX: Query name collision with multiple filters https://meta.discourse.org/t/error-when-adding-3-or-4-filters-to-knowledge-explorer-plugin/167123/ If using more than two tags to filter, we'd run into an SQL alias collision on a few joins. Resolved by ensuring unique names are used across the query. --- lib/knowledge_explorer/query.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/knowledge_explorer/query.rb b/lib/knowledge_explorer/query.rb index 5527811..9bbb6af 100644 --- a/lib/knowledge_explorer/query.rb +++ b/lib/knowledge_explorer/query.rb @@ -37,7 +37,7 @@ def list if tags_count == tag_filters.length tag_filters.each_with_index do |tag, index| # to_i to make it clear this is not an injection - sql_alias = "t#{index.to_i}" + sql_alias = "tt#{index.to_i}" results = results.joins("INNER JOIN topic_tags #{sql_alias} ON #{sql_alias}.topic_id = topics.id AND #{sql_alias}.tag_id = #{tag}") end else @@ -91,8 +91,8 @@ def list # conduct a second set of joins so we don't mess up the count count_query = results.joins <<~SQL - INNER JOIN topic_tags tt2 ON tt2.topic_id = topics.id - INNER JOIN tags t2 ON t2.id = tt2.tag_id + INNER JOIN topic_tags ttx ON ttx.topic_id = topics.id + INNER JOIN tags t2 ON t2.id = ttx.tag_id SQL tags = count_query.group('t2.name').count tags = create_tags_object(tags) From 099bdf5ed4f72eaecdaf3dd03bcefbc08e8399e8 Mon Sep 17 00:00:00 2001 From: Justin DiRose Date: Wed, 14 Oct 2020 09:16:49 -0500 Subject: [PATCH 2/2] DEV: Add specs to cover multi-tag filter --- .../knowledge_explorer_controller_spec.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/spec/requests/knowledge_explorer_controller_spec.rb b/spec/requests/knowledge_explorer_controller_spec.rb index fe9b251..594fcac 100644 --- a/spec/requests/knowledge_explorer_controller_spec.rb +++ b/spec/requests/knowledge_explorer_controller_spec.rb @@ -63,16 +63,30 @@ end context 'when filtering by tag' do + fab!(:tag2) { Fabricate(:tag, topics: [topic], name: 'test2') } + fab!(:tag3) { Fabricate(:tag, topics: [topic], name: 'test3') } + it 'should return a list filtered by tag' do get '/docs.json?tags=test' expect(response.status).to eq(200) json = JSON.parse(response.body) + topics = json['topics']['topic_list']['topics'] + + expect(topics.size).to eq(1) + end + + it 'should properly filter with more than two tags' do + get '/docs.json?tags=test%7ctest2%7ctest3' + + expect(response.status).to eq(200) + + json = response.parsed_body tags = json['tags'] topics = json['topics']['topic_list']['topics'] - expect(tags.size).to eq(1) + expect(tags.size).to eq(3) expect(topics.size).to eq(1) end end