From 93a80b7f7cf9e02ddfcbd400725827eafec13fc5 Mon Sep 17 00:00:00 2001
From: Heinrich Lee Yu <heinrich@gitlab.com>
Date: Mon, 17 May 2021 16:43:57 +0800
Subject: [PATCH] Fix issuable search optimization in PG12

Uses a materialized CTE so that our optimization fence actually works.

Recursive CTEs are materialized by default in PG12 but we're not using
this recursively here so we use Gitlab::SQL::CTE which handles adding of
the MATERIALIZED keyword when needed.

Changelog: fixed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61880
---
 app/finders/issuable_finder.rb                               | 3 +--
 .../unreleased/331089-issue-search-materialized-cte.yml      | 5 +++++
 spec/finders/issues_finder_spec.rb                           | 2 ++
 3 files changed, 8 insertions(+), 2 deletions(-)
 create mode 100644 changelogs/unreleased/331089-issue-search-materialized-cte.yml

diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 1232297db1bb5..d1885b5ae08c7 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -334,8 +334,7 @@ def by_search(items)
     return items if items.is_a?(ActiveRecord::NullRelation)
 
     if use_cte_for_search?
-      cte = Gitlab::SQL::RecursiveCTE.new(klass.table_name)
-      cte << items
+      cte = Gitlab::SQL::CTE.new(klass.table_name, items)
 
       items = klass.with(cte.to_arel).from(klass.table_name)
     end
diff --git a/changelogs/unreleased/331089-issue-search-materialized-cte.yml b/changelogs/unreleased/331089-issue-search-materialized-cte.yml
new file mode 100644
index 0000000000000..0b9a1a3490b74
--- /dev/null
+++ b/changelogs/unreleased/331089-issue-search-materialized-cte.yml
@@ -0,0 +1,5 @@
+---
+title: Fix issuable search optimization in PG12
+merge_request: 61880
+author:
+type: fixed
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index a2aac857bf5f0..27466ab563f59 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -1178,6 +1178,7 @@
 
         it 'returns true' do
           expect(finder.use_cte_for_search?).to be_truthy
+          expect(finder.execute.to_sql).to match(/^WITH "issues" AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}/)
         end
       end
 
@@ -1186,6 +1187,7 @@
 
         it 'returns true' do
           expect(finder.use_cte_for_search?).to be_truthy
+          expect(finder.execute.to_sql).to match(/^WITH "issues" AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported}/)
         end
       end
     end
-- 
GitLab