diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index 314d5b18a..7ef9a5318 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -195,30 +195,19 @@ class PostQueryBuilder relation = relation.where.not("posts.file_ext": q[:filetype_neg]) end - # The SourcePattern SQL function replaces Pixiv sources with "pixiv/[suffix]", where - # [suffix] is everything past the second-to-last slash in the URL. It leaves non-Pixiv - # URLs unchanged. This is to ease database load for Pixiv source searches. if q[:source] - if q[:source] == "none%" + if q[:source] == "none" relation = relation.where("posts.source = ''") - elsif q[:source] == "http%" - relation = relation.where("(lower(posts.source) like ?)", "http%") - elsif q[:source] =~ /^(?:https?:\/\/)?%\.?pixiv(?:\.net(?:\/img)?)?(?:%\/img\/|%\/|(?=%$))(.+)$/i - relation = relation.where("SourcePattern(lower(posts.source)) LIKE lower(?) ESCAPE E'\\\\'", "pixiv/" + $1) else - relation = relation.where("SourcePattern(lower(posts.source)) LIKE SourcePattern(lower(?)) ESCAPE E'\\\\'", q[:source]) + relation = relation.where_ilike(:source, q[:source].downcase + "*") end end if q[:source_neg] - if q[:source_neg] == "none%" + if q[:source_neg] == "none" relation = relation.where("posts.source != ''") - elsif q[:source_neg] == "http%" - relation = relation.where("(lower(posts.source) not like ?)", "http%") - elsif q[:source_neg] =~ /^(?:https?:\/\/)?%\.?pixiv(?:\.net(?:\/img)?)?(?:%\/img\/|%\/|(?=%$))(.+)$/i - relation = relation.where("SourcePattern(lower(posts.source)) NOT LIKE lower(?) ESCAPE E'\\\\'", "pixiv/" + $1) else - relation = relation.where("SourcePattern(lower(posts.source)) NOT LIKE SourcePattern(lower(?)) ESCAPE E'\\\\'", q[:source_neg]) + relation = relation.where_not_ilike(:source, q[:source_neg].downcase + "*") end end diff --git a/app/models/tag.rb b/app/models/tag.rb index 2463b8488..503c5ee19 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -751,12 +751,10 @@ class Tag < ApplicationRecord q[:filesize] = parse_helper_fudged(g2, :filesize) when "source" - src = g2.gsub(/\A"(.*)"\Z/, '\1') - q[:source] = (src.to_escaped_for_sql_like + "%").gsub(/%+/, '%') + q[:source] = g2.gsub(/\A"(.*)"\Z/, '\1') when "-source" - src = g2.gsub(/\A"(.*)"\Z/, '\1') - q[:source_neg] = (src.to_escaped_for_sql_like + "%").gsub(/%+/, '%') + q[:source_neg] = g2.gsub(/\A"(.*)"\Z/, '\1') when "date" q[:date] = parse_helper(g2, :date) diff --git a/db/migrate/20190829055758_drop_source_pattern_index_on_posts.rb b/db/migrate/20190829055758_drop_source_pattern_index_on_posts.rb new file mode 100644 index 000000000..e36b05629 --- /dev/null +++ b/db/migrate/20190829055758_drop_source_pattern_index_on_posts.rb @@ -0,0 +1,24 @@ +# see db/migrate/20130328092739_change_source_pattern_index_on_posts.rb + +class DropSourcePatternIndexOnPosts < ActiveRecord::Migration[6.0] + def up + execute "set statement_timeout = 0" + + execute "DROP INDEX index_posts_on_source_pattern" + execute "DROP FUNCTION SourcePattern(text)" + add_index :posts, "lower(source) gin_trgm_ops", name: "index_posts_on_source_trgm", using: :gin, where: "source != ''" + end + + def down + execute "set statement_timeout = 0" + + remove_index :posts, name: "index_posts_on_source_trgm" + execute "CREATE FUNCTION SourcePattern(src text) RETURNS text AS $$ + BEGIN + RETURN regexp_replace(src, '^[^/]*(//)?[^/]*\.pixiv\.net/img.*(/[^/]*/[^/]*)$', E'pixiv\\\\2'); + END; + $$ LANGUAGE plpgsql IMMUTABLE RETURNS NULL ON NULL INPUT" + execute "CREATE INDEX index_posts_on_source_pattern ON posts USING btree + ((SourcePattern(source)) text_pattern_ops)" + end +end diff --git a/db/structure.sql b/db/structure.sql index fc403b707..83556d72c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -336,19 +336,6 @@ CREATE FUNCTION public.favorites_insert_trigger() RETURNS trigger $$; --- --- Name: sourcepattern(text); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.sourcepattern(src text) RETURNS text - LANGUAGE plpgsql IMMUTABLE STRICT - AS $_$ - BEGIN - RETURN regexp_replace(src, '^[^/]*(//)?[^/]*.pixiv.net/img.*(/[^/]*/[^/]*)$', E'pixiv\\2'); - END; - $_$; - - -- -- Name: testprs_end(internal); Type: FUNCTION; Schema: public; Owner: - -- @@ -6779,10 +6766,10 @@ CREATE INDEX index_posts_on_pixiv_id ON public.posts USING btree (pixiv_id) WHER -- --- Name: index_posts_on_source_pattern; Type: INDEX; Schema: public; Owner: - +-- Name: index_posts_on_source_trgm; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_posts_on_source_pattern ON public.posts USING btree (public.sourcepattern(lower((source)::text)) text_pattern_ops); +CREATE INDEX index_posts_on_source_trgm ON public.posts USING gin (lower((source)::text) public.gin_trgm_ops) WHERE ((source)::text <> ''::text); -- @@ -7327,6 +7314,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20190827233235'), ('20190827234625'), ('20190828005453'), -('20190829052629'); +('20190829052629'), +('20190829055758'); diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index 209b8e045..061ab978d 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -2206,8 +2206,6 @@ class PostTest < ActiveSupport::TestCase assert_tag_match([], "source:*.pixiv.net/img*/artist-fake/*") assert_tag_match([post], "source:http://*.pixiv.net/img*/img/artist-name/*") assert_tag_match([], "source:http://*.pixiv.net/img*/img/artist-fake/*") - assert_tag_match([post], "source:pixiv/artist-name/*") - assert_tag_match([], "source:pixiv/artist-fake/*") end should "return posts for a pixiv id search (type 1)" do