From e95439c8f194c61501088a01a1ec4da7a0864b08 Mon Sep 17 00:00:00 2001
From: Patrick Cloke <patrickc@matrix.org>
Date: Thu, 27 Oct 2022 08:32:47 -0400
Subject: [PATCH 1/3] Fix tests for changein PostgreSQL 14 behavior change.

---
 synapse/storage/databases/main/search.py |  5 ++---
 tests/storage/test_room_search.py        | 15 +++++++++++----
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/synapse/storage/databases/main/search.py b/synapse/storage/databases/main/search.py
index a89fc54c2cbe..594b935614f7 100644
--- a/synapse/storage/databases/main/search.py
+++ b/synapse/storage/databases/main/search.py
@@ -824,9 +824,8 @@ def _tokenize_query(query: str) -> TokenList:
     in_phrase = False
     parts = deque(query.split('"'))
     for i, part in enumerate(parts):
-        # The contents inside double quotes is treated as a phrase, a trailing
-        # double quote is not implied.
-        in_phrase = bool(i % 2) and i != (len(parts) - 1)
+        # The contents inside double quotes is treated as a phrase.
+        in_phrase = bool(i % 2)
 
         # Pull out the individual words, discarding any non-word characters.
         words = deque(re.findall(r"([\w\-]+)", part, re.UNICODE))
diff --git a/tests/storage/test_room_search.py b/tests/storage/test_room_search.py
index 9ddc19900afc..7034ec2f20f3 100644
--- a/tests/storage/test_room_search.py
+++ b/tests/storage/test_room_search.py
@@ -239,7 +239,6 @@ class MessageSearchTest(HomeserverTestCase):
         ("fox -nope", (True, False)),
         ("fox -brown", (False, True)),
         ('"fox" quick', True),
-        ('"fox quick', True),
         ('"quick brown', True),
         ('" quick "', True),
         ('" nope"', False),
@@ -269,6 +268,14 @@ def prepare(
         response = self.helper.send(self.room_id, self.PHRASE, tok=self.access_token)
         self.assertIn("event_id", response)
 
+        # The behaviour of a missing trailing double quote changed in PostgreSQL 14
+        # from ignoring the initial double quote to treating it as a phrase.
+        main_store = homeserver.get_datastores().main
+        found = False
+        if isinstance(main_store.database_engine, PostgresEngine):
+            found = main_store.database_engine._version < 140000
+        self.COMMON_CASES.append(('"fox quick', (found, True)))
+
     def test_tokenize_query(self) -> None:
         """Test the custom logic to tokenize a user's query."""
         cases = (
@@ -280,9 +287,9 @@ def test_tokenize_query(self) -> None:
             ("fox -brown", ["fox", SearchToken.Not, "brown"]),
             ("- fox", [SearchToken.Not, "fox"]),
             ('"fox" quick', [Phrase(["fox"]), SearchToken.And, "quick"]),
-            # No trailing double quoe.
-            ('"fox quick', ["fox", SearchToken.And, "quick"]),
-            ('"-fox quick', [SearchToken.Not, "fox", SearchToken.And, "quick"]),
+            # No trailing double quote.
+            ('"fox quick', [Phrase(["fox", "quick"])]),
+            ('"-fox quick', [Phrase(["-fox", "quick"])]),
             ('" quick "', [Phrase(["quick"])]),
             (
                 'q"uick brow"n',

From 8e432645978c52811f500b449c2ef79bc140b6d5 Mon Sep 17 00:00:00 2001
From: Patrick Cloke <patrickc@matrix.org>
Date: Thu, 27 Oct 2022 08:36:24 -0400
Subject: [PATCH 2/3] Newsfragment

---
 changelog.d/14310.feature | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 changelog.d/14310.feature

diff --git a/changelog.d/14310.feature b/changelog.d/14310.feature
new file mode 100644
index 000000000000..94c8a83212d1
--- /dev/null
+++ b/changelog.d/14310.feature
@@ -0,0 +1 @@
+Allow use of postgres and sqllite full-text search operators in search queries.
\ No newline at end of file

From 91b475d1836d4b0092d00157366d83144d8159f9 Mon Sep 17 00:00:00 2001
From: Patrick Cloke <patrickc@matrix.org>
Date: Thu, 27 Oct 2022 09:19:31 -0400
Subject: [PATCH 3/3] Lint

---
 tests/storage/test_room_search.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/storage/test_room_search.py b/tests/storage/test_room_search.py
index 7034ec2f20f3..868b5bee8485 100644
--- a/tests/storage/test_room_search.py
+++ b/tests/storage/test_room_search.py
@@ -273,6 +273,7 @@ def prepare(
         main_store = homeserver.get_datastores().main
         found = False
         if isinstance(main_store.database_engine, PostgresEngine):
+            assert main_store.database_engine._version is not None
             found = main_store.database_engine._version < 140000
         self.COMMON_CASES.append(('"fox quick', (found, True)))