commit 296f01b1c2fe92aa834b7f199155e41618d122d0
Author: Alexander Korotkov <akorotkov@postgresql.org>
Date:   Fri Jan 29 16:49:34 2021 +0300

    Fix parsing of complex morphs to tsquery
    
    When to_tsquery() or websearch_to_tsquery() meet a complex morph containing
    multiple words residing adjacent position, these words are connected
    with OP_AND operator.  That leads to surprising results.  For instace,
    both websearch_to_tsquery('"pg_class pg"') and to_tsquery('pg_class <-> pg')
    produce '( pg & class ) <-> pg' tsquery.  This tsquery requires
    'pg' and 'class' words to reside on the same position and doesn't match
    to to_tsvector('pg_class pg').  It appears to be ridiculous behavior, which
    needs to be fixed.
    
    This commit makes to_tsquery() or websearch_to_tsquery() connect words
    residing adjacent position with OP_PHRASE.  Therefore, now those words are
    normally chained with other OP_PHRASE operator.  The examples of above now
    produces 'pg <-> class <-> pg' tsquery, which matches to
    to_tsvector('pg_class pg').
    
    Another effect of this commit is that complex morph word positions now need to
    match the tsvector even if there is no surrounding OP_PHRASE.  This behavior
    change generally looks like an improvement but making this commit not
    backpatchable.
    
    Reported-by: Barry Pederson
    Bug: #16592
    Discussion: https://postgr.es/m/16592-70b110ff9731c07d@postgresql.org
    Discussion: https://postgr.es/m/CAPpHfdv0EzVhf6CWfB1_TTZqXV_2Sn-jSY3zSd7ePH%3D-%2B1V2DQ%40mail.gmail.com
    Author: Alexander Korotkov
    Reviewed-by: Tom Lane, Neil Chen

diff --git a/src/backend/tsearch/to_tsany.c b/src/backend/tsearch/to_tsany.c
index e7cd6264db2..3cfd3e01c8c 100644
--- a/src/backend/tsearch/to_tsany.c
+++ b/src/backend/tsearch/to_tsany.c
@@ -20,10 +20,20 @@
 #include "utils/jsonfuncs.h"
 
 
+/*
+ * Opaque data structure, which is passed by parse_tsquery() to pushval_morph().
+ */
 typedef struct MorphOpaque
 {
 	Oid			cfg_id;
-	int			qoperator;		/* query operator */
+
+	/*
+	 * Single tsquery morph could be parsed into multiple words.  When these
+	 * words reside in adjacent positions, they are connected using this
+	 * operator.  Usually, that is OP_PHRASE, which requires word positions of
+	 * a complex morph to exactly match the tsvector.
+	 */
+	int			qoperator;
 } MorphOpaque;
 
 typedef struct TSVectorBuildState
@@ -573,7 +583,14 @@ to_tsquery_byid(PG_FUNCTION_ARGS)
 	MorphOpaque data;
 
 	data.cfg_id = PG_GETARG_OID(0);
-	data.qoperator = OP_AND;
+
+	/*
+	 * Passing OP_PHRASE as a qoperator makes tsquery require matching of word
+	 * positions of a complex morph exactly match the tsvector.  Also, when
+	 * the complex morphs are connected with OP_PHRASE operator, we connect
+	 * all their words into the OP_PHRASE sequence.
+	 */
+	data.qoperator = OP_PHRASE;
 
 	query = parse_tsquery(text_to_cstring(in),
 						  pushval_morph,
@@ -603,6 +620,12 @@ plainto_tsquery_byid(PG_FUNCTION_ARGS)
 	MorphOpaque data;
 
 	data.cfg_id = PG_GETARG_OID(0);
+
+	/*
+	 * parse_tsquery() with P_TSQ_PLAIN flag takes the whole input text as a
+	 * single morph.  Passing OP_PHRASE as a qoperator makes tsquery require
+	 * matching of all words independently on their positions.
+	 */
 	data.qoperator = OP_AND;
 
 	query = parse_tsquery(text_to_cstring(in),
@@ -634,6 +657,12 @@ phraseto_tsquery_byid(PG_FUNCTION_ARGS)
 	MorphOpaque data;
 
 	data.cfg_id = PG_GETARG_OID(0);
+
+	/*
+	 * parse_tsquery() with P_TSQ_PLAIN flag takes the whole input text as a
+	 * single morph.  Passing OP_PHRASE as a qoperator makes tsquery require
+	 * matching of word positions.
+	 */
 	data.qoperator = OP_PHRASE;
 
 	query = parse_tsquery(text_to_cstring(in),
@@ -665,7 +694,13 @@ websearch_to_tsquery_byid(PG_FUNCTION_ARGS)
 
 	data.cfg_id = PG_GETARG_OID(0);
 
-	data.qoperator = OP_AND;
+	/*
+	 * Passing OP_PHRASE as a qoperator makes tsquery require matching of word
+	 * positions of a complex morph exactly match the tsvector.  Also, when
+	 * the complex morphs are given in quotes, we connect all their words into
+	 * the OP_PHRASE sequence.
+	 */
+	data.qoperator = OP_PHRASE;
 
 	query = parse_tsquery(text_to_cstring(in),
 						  pushval_morph,
diff --git a/src/test/regress/expected/tsearch.out b/src/test/regress/expected/tsearch.out
index 0110b4d2e0d..4ae62320c9f 100644
--- a/src/test/regress/expected/tsearch.out
+++ b/src/test/regress/expected/tsearch.out
@@ -1997,31 +1997,31 @@ ALTER TABLE test_tsquery ADD COLUMN keyword tsquery;
 UPDATE test_tsquery SET keyword = to_tsquery('english', txtkeyword);
 ALTER TABLE test_tsquery ADD COLUMN sample tsquery;
 UPDATE test_tsquery SET sample = to_tsquery('english', txtsample::text);
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new <-> york';
  count 
 -------
      2
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new <-> york';
  count 
 -------
      3
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new <-> york';
  count 
 -------
      1
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new <-> york';
  count 
 -------
      4
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new <-> york';
  count 
 -------
      3
@@ -2029,31 +2029,31 @@ SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new & york';
 
 CREATE UNIQUE INDEX bt_tsq ON test_tsquery (keyword);
 SET enable_seqscan=OFF;
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new <-> york';
  count 
 -------
      2
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new <-> york';
  count 
 -------
      3
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new <-> york';
  count 
 -------
      1
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new <-> york';
  count 
 -------
      4
 (1 row)
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new <-> york';
  count 
 -------
      3
@@ -2085,10 +2085,10 @@ SELECT ts_rewrite('moscow & hotel', 'SELECT keyword, sample FROM test_tsquery'::
  'hotel' & ( 'moskva' | 'moscow' )
 (1 row)
 
-SELECT ts_rewrite('bar & new & qq & foo & york', 'SELECT keyword, sample FROM test_tsquery'::text );
-                                   ts_rewrite                                    
----------------------------------------------------------------------------------
- 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' & 'appl' | 'new' & 'york' )
+SELECT ts_rewrite('bar & qq & foo & (new <-> york)', 'SELECT keyword, sample FROM test_tsquery'::text );
+                                     ts_rewrite                                      
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' <-> 'appl' | 'new' <-> 'york' )
 (1 row)
 
 SELECT ts_rewrite( 'moscow', 'SELECT keyword, sample FROM test_tsquery');
@@ -2103,10 +2103,10 @@ SELECT ts_rewrite( 'moscow & hotel', 'SELECT keyword, sample FROM test_tsquery')
  'hotel' & ( 'moskva' | 'moscow' )
 (1 row)
 
-SELECT ts_rewrite( 'bar & new & qq & foo & york', 'SELECT keyword, sample FROM test_tsquery');
-                                   ts_rewrite                                    
----------------------------------------------------------------------------------
- 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' & 'appl' | 'new' & 'york' )
+SELECT ts_rewrite( 'bar & qq & foo & (new <-> york)', 'SELECT keyword, sample FROM test_tsquery');
+                                     ts_rewrite                                      
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' <-> 'appl' | 'new' <-> 'york' )
 (1 row)
 
 SELECT ts_rewrite('1 & (2 <-> 3)', 'SELECT keyword, sample FROM test_tsquery'::text );
@@ -2149,9 +2149,9 @@ NOTICE:  text-search query doesn't contain lexemes: ""
 (1 row)
 
 SELECT keyword FROM test_tsquery WHERE keyword @> 'new';
-    keyword     
-----------------
- 'new' & 'york'
+     keyword      
+------------------
+ 'new' <-> 'york'
 (1 row)
 
 SELECT keyword FROM test_tsquery WHERE keyword @> 'moscow';
@@ -2183,10 +2183,10 @@ SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_t
  'hotel' & ( 'moskva' | 'moscow' )
 (1 row)
 
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar &  new & qq & foo & york') AS query;
-                                   ts_rewrite                                    
----------------------------------------------------------------------------------
- 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' & 'appl' | 'new' & 'york' )
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
+                                     ts_rewrite                                      
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' <-> 'appl' | 'new' <-> 'york' )
 (1 row)
 
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow') AS query;
@@ -2201,18 +2201,18 @@ SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_t
  'hotel' & ( 'moskva' | 'moscow' )
 (1 row)
 
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & new & qq & foo & york') AS query;
-                                   ts_rewrite                                    
----------------------------------------------------------------------------------
- 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' & 'appl' | 'new' & 'york' )
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
+                                     ts_rewrite                                      
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' <-> 'appl' | 'new' <-> 'york' )
 (1 row)
 
 CREATE INDEX qq ON test_tsquery USING gist (keyword tsquery_ops);
 SET enable_seqscan=OFF;
 SELECT keyword FROM test_tsquery WHERE keyword @> 'new';
-    keyword     
-----------------
- 'new' & 'york'
+     keyword      
+------------------
+ 'new' <-> 'york'
 (1 row)
 
 SELECT keyword FROM test_tsquery WHERE keyword @> 'moscow';
@@ -2244,10 +2244,10 @@ SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_t
  'hotel' & ( 'moskva' | 'moscow' )
 (1 row)
 
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & new & qq & foo & york') AS query;
-                                   ts_rewrite                                    
----------------------------------------------------------------------------------
- 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' & 'appl' | 'new' & 'york' )
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
+                                     ts_rewrite                                      
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' <-> 'appl' | 'new' <-> 'york' )
 (1 row)
 
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow') AS query;
@@ -2262,10 +2262,10 @@ SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_t
  'hotel' & ( 'moskva' | 'moscow' )
 (1 row)
 
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar &  new & qq & foo & york') AS query;
-                                   ts_rewrite                                    
----------------------------------------------------------------------------------
- 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' & 'appl' | 'new' & 'york' )
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
+                                     ts_rewrite                                      
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | 'big' <-> 'appl' | 'new' <-> 'york' )
 (1 row)
 
 SELECT ts_rewrite(tsquery_phrase('foo', 'foo'), 'foo', 'bar | baz');
@@ -2456,19 +2456,19 @@ select websearch_to_tsquery('simple', 'fat:A : cat:B');
 select websearch_to_tsquery('simple', 'fat*rat');
  websearch_to_tsquery 
 ----------------------
- 'fat' & 'rat'
+ 'fat' <-> 'rat'
 (1 row)
 
 select websearch_to_tsquery('simple', 'fat-rat');
-   websearch_to_tsquery    
----------------------------
- 'fat-rat' & 'fat' & 'rat'
+     websearch_to_tsquery      
+-------------------------------
+ 'fat-rat' <-> 'fat' <-> 'rat'
 (1 row)
 
 select websearch_to_tsquery('simple', 'fat_rat');
  websearch_to_tsquery 
 ----------------------
- 'fat' & 'rat'
+ 'fat' <-> 'rat'
 (1 row)
 
 -- weights are completely ignored
@@ -2665,64 +2665,64 @@ select websearch_to_tsquery('simple', 'abc OR1234');
 (1 row)
 
 select websearch_to_tsquery('simple', 'abc or-abc');
-      websearch_to_tsquery       
----------------------------------
- 'abc' & 'or-abc' & 'or' & 'abc'
+        websearch_to_tsquery         
+-------------------------------------
+ 'abc' & 'or-abc' <-> 'or' <-> 'abc'
 (1 row)
 
 select websearch_to_tsquery('simple', 'abc OR_abc');
- websearch_to_tsquery 
-----------------------
- 'abc' & 'or' & 'abc'
+  websearch_to_tsquery  
+------------------------
+ 'abc' & 'or' <-> 'abc'
 (1 row)
 
 -- test quotes
 select websearch_to_tsquery('english', '"pg_class pg');
- websearch_to_tsquery  
------------------------
- 'pg' & 'class' & 'pg'
+  websearch_to_tsquery   
+-------------------------
+ 'pg' <-> 'class' & 'pg'
 (1 row)
 
 select websearch_to_tsquery('english', 'pg_class pg"');
- websearch_to_tsquery  
------------------------
- 'pg' & 'class' & 'pg'
+  websearch_to_tsquery   
+-------------------------
+ 'pg' <-> 'class' & 'pg'
 (1 row)
 
 select websearch_to_tsquery('english', '"pg_class pg"');
-    websearch_to_tsquery     
------------------------------
- ( 'pg' & 'class' ) <-> 'pg'
+   websearch_to_tsquery    
+---------------------------
+ 'pg' <-> 'class' <-> 'pg'
 (1 row)
 
 select websearch_to_tsquery('english', 'abc "pg_class pg"');
-        websearch_to_tsquery         
--------------------------------------
- 'abc' & ( 'pg' & 'class' ) <-> 'pg'
+       websearch_to_tsquery        
+-----------------------------------
+ 'abc' & 'pg' <-> 'class' <-> 'pg'
 (1 row)
 
 select websearch_to_tsquery('english', '"pg_class pg" def');
-        websearch_to_tsquery         
--------------------------------------
- ( 'pg' & 'class' ) <-> 'pg' & 'def'
+       websearch_to_tsquery        
+-----------------------------------
+ 'pg' <-> 'class' <-> 'pg' & 'def'
 (1 row)
 
 select websearch_to_tsquery('english', 'abc "pg pg_class pg" def');
-                 websearch_to_tsquery                 
-------------------------------------------------------
- 'abc' & 'pg' <-> ( 'pg' & 'class' ) <-> 'pg' & 'def'
+                  websearch_to_tsquery                  
+--------------------------------------------------------
+ 'abc' & 'pg' <-> ( 'pg' <-> 'class' ) <-> 'pg' & 'def'
 (1 row)
 
 select websearch_to_tsquery('english', ' or "pg pg_class pg" or ');
-         websearch_to_tsquery         
---------------------------------------
- 'pg' <-> ( 'pg' & 'class' ) <-> 'pg'
+          websearch_to_tsquery          
+----------------------------------------
+ 'pg' <-> ( 'pg' <-> 'class' ) <-> 'pg'
 (1 row)
 
 select websearch_to_tsquery('english', '""pg pg_class pg""');
-     websearch_to_tsquery     
-------------------------------
- 'pg' & 'pg' & 'class' & 'pg'
+      websearch_to_tsquery      
+--------------------------------
+ 'pg' & 'pg' <-> 'class' & 'pg'
 (1 row)
 
 select websearch_to_tsquery('english', 'abc """"" def');
@@ -2829,7 +2829,7 @@ NOTICE:  text-search query contains only stop words or doesn't contain lexemes,
 select websearch_to_tsquery('''abc''''def''');
  websearch_to_tsquery 
 ----------------------
- 'abc' & 'def'
+ 'abc' <-> 'def'
 (1 row)
 
 select websearch_to_tsquery('\abc');
diff --git a/src/test/regress/sql/tsearch.sql b/src/test/regress/sql/tsearch.sql
index 8a27fcd8b0b..b02ed73f6a8 100644
--- a/src/test/regress/sql/tsearch.sql
+++ b/src/test/regress/sql/tsearch.sql
@@ -554,10 +554,10 @@ to_tsquery('english','Lorem') && phraseto_tsquery('english','ullamcorper urna'),
 CREATE TABLE test_tsquery (txtkeyword TEXT, txtsample TEXT);
 \set ECHO none
 \copy test_tsquery from stdin
-'New York'	new & york | big & apple | nyc
+'New York'	new <-> york | big <-> apple | nyc
 Moscow	moskva | moscow
 'Sanct Peter'	Peterburg | peter | 'Sanct Peterburg'
-'foo bar qq'	foo & (bar | qq) & city
+foo & bar & qq	foo & (bar | qq) & city
 1 & (2 <-> 3)	2 <-> 4
 5 <-> 6	5 <-> 7
 \.
@@ -569,21 +569,21 @@ ALTER TABLE test_tsquery ADD COLUMN sample tsquery;
 UPDATE test_tsquery SET sample = to_tsquery('english', txtsample::text);
 
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new <-> york';
 
 CREATE UNIQUE INDEX bt_tsq ON test_tsquery (keyword);
 
 SET enable_seqscan=OFF;
 
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new & york';
-SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new & york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <  'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword <= 'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword = 'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >= 'new <-> york';
+SELECT COUNT(*) FROM test_tsquery WHERE keyword >  'new <-> york';
 
 RESET enable_seqscan;
 
@@ -593,11 +593,11 @@ SELECT ts_rewrite(ts_rewrite('new & !york ', 'york', '!jersey'),
 
 SELECT ts_rewrite('moscow', 'SELECT keyword, sample FROM test_tsquery'::text );
 SELECT ts_rewrite('moscow & hotel', 'SELECT keyword, sample FROM test_tsquery'::text );
-SELECT ts_rewrite('bar & new & qq & foo & york', 'SELECT keyword, sample FROM test_tsquery'::text );
+SELECT ts_rewrite('bar & qq & foo & (new <-> york)', 'SELECT keyword, sample FROM test_tsquery'::text );
 
 SELECT ts_rewrite( 'moscow', 'SELECT keyword, sample FROM test_tsquery');
 SELECT ts_rewrite( 'moscow & hotel', 'SELECT keyword, sample FROM test_tsquery');
-SELECT ts_rewrite( 'bar & new & qq & foo & york', 'SELECT keyword, sample FROM test_tsquery');
+SELECT ts_rewrite( 'bar & qq & foo & (new <-> york)', 'SELECT keyword, sample FROM test_tsquery');
 
 SELECT ts_rewrite('1 & (2 <-> 3)', 'SELECT keyword, sample FROM test_tsquery'::text );
 SELECT ts_rewrite('1 & (2 <2> 3)', 'SELECT keyword, sample FROM test_tsquery'::text );
@@ -614,10 +614,10 @@ SELECT keyword FROM test_tsquery WHERE keyword <@ 'new';
 SELECT keyword FROM test_tsquery WHERE keyword <@ 'moscow';
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow') AS query;
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow & hotel') AS query;
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar &  new & qq & foo & york') AS query;
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow') AS query;
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow & hotel') AS query;
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & new & qq & foo & york') AS query;
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
 
 CREATE INDEX qq ON test_tsquery USING gist (keyword tsquery_ops);
 SET enable_seqscan=OFF;
@@ -628,10 +628,10 @@ SELECT keyword FROM test_tsquery WHERE keyword <@ 'new';
 SELECT keyword FROM test_tsquery WHERE keyword <@ 'moscow';
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow') AS query;
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow & hotel') AS query;
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & new & qq & foo & york') AS query;
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow') AS query;
 SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'moscow & hotel') AS query;
-SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar &  new & qq & foo & york') AS query;
+SELECT ts_rewrite( query, 'SELECT keyword, sample FROM test_tsquery' ) FROM to_tsquery('english', 'bar & qq & foo & (new <-> york)') AS query;
 
 SELECT ts_rewrite(tsquery_phrase('foo', 'foo'), 'foo', 'bar | baz');
 SELECT to_tsvector('foo bar') @@
