Resurrect the code for the rewrite(ARRAY[...]) aggregate function,
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 13 Nov 2007 22:14:50 +0000 (22:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 13 Nov 2007 22:14:50 +0000 (22:14 +0000)
and put it into contrib/tsearch2 compatibility module.

contrib/tsearch2/expected/tsearch2.out
contrib/tsearch2/sql/tsearch2.sql
contrib/tsearch2/tsearch2.c
contrib/tsearch2/tsearch2.sql.in
src/backend/utils/adt/tsquery_rewrite.c
src/include/tsearch/ts_utils.h

index d4a81f69cb35f47b5e21d1e0487326c08d4b9f28..6fb820c3cff0d3966b523afcf9045dd00eab95de 100644 (file)
@@ -472,6 +472,24 @@ select rewrite('bar &  new & qq & foo & york', 'select keyword, sample from test
  'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | ( 'big' & 'appl' | 'new' & 'york' ) )
 (1 row)
 
+select rewrite( ARRAY['moscow', keyword, sample] ) from test_tsquery;
+       rewrite       
+---------------------
+ 'moskva' | 'moscow'
+(1 row)
+
+select rewrite( ARRAY['moscow & hotel', keyword, sample] ) from test_tsquery;
+              rewrite              
+-----------------------------------
+ ( 'moskva' | 'moscow' ) & 'hotel'
+(1 row)
+
+select rewrite( ARRAY['bar &  new & qq & foo & york', keyword, sample] ) from test_tsquery;
+                                       rewrite                                       
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | ( 'big' & 'appl' | 'new' & 'york' ) )
+(1 row)
+
 select keyword from test_tsquery where keyword @> 'new';
     keyword     
 ----------------
@@ -495,6 +513,42 @@ select keyword from test_tsquery where keyword <@ 'moscow';
  'moscow'
 (1 row)
 
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where keyword <@ query;
+       rewrite       
+---------------------
+ 'moskva' | 'moscow'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where keyword <@ query;
+              rewrite              
+-----------------------------------
+ ( 'moskva' | 'moscow' ) & 'hotel'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where keyword <@ query;
+                                       rewrite                                       
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | ( 'big' & 'appl' | 'new' & 'york' ) )
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where query @> keyword;
+       rewrite       
+---------------------
+ 'moskva' | 'moscow'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where query @> keyword;
+              rewrite              
+-----------------------------------
+ ( 'moskva' | 'moscow' ) & 'hotel'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where query @> keyword;
+                                       rewrite                                       
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | ( 'big' & 'appl' | 'new' & 'york' ) )
+(1 row)
+
 create index qq on test_tsquery using gist (keyword gist_tp_tsquery_ops);
 set enable_seqscan='off';
 select keyword from test_tsquery where keyword @> 'new';
@@ -520,6 +574,42 @@ select keyword from test_tsquery where keyword <@ 'moscow';
  'moscow'
 (1 row)
 
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where keyword <@ query;
+       rewrite       
+---------------------
+ 'moskva' | 'moscow'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where keyword <@ query;
+              rewrite              
+-----------------------------------
+ ( 'moskva' | 'moscow' ) & 'hotel'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where keyword <@ query;
+                                       rewrite                                       
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | ( 'big' & 'appl' | 'new' & 'york' ) )
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where query @> keyword;
+       rewrite       
+---------------------
+ 'moskva' | 'moscow'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where query @> keyword;
+              rewrite              
+-----------------------------------
+ ( 'moskva' | 'moscow' ) & 'hotel'
+(1 row)
+
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where query @> keyword;
+                                       rewrite                                       
+-------------------------------------------------------------------------------------
+ 'citi' & 'foo' & ( 'bar' | 'qq' ) & ( 'nyc' | ( 'big' & 'appl' | 'new' & 'york' ) )
+(1 row)
+
 set enable_seqscan='on';
 select lexize('simple', 'ASD56 hsdkf');
      lexize      
index a7f8e8d267d55bf9e76a92637c4958060b05d742..b20055c45c68060389fe607de458d8f0c760081d 100644 (file)
@@ -116,10 +116,21 @@ select rewrite('moscow', 'select keyword, sample from test_tsquery'::text );
 select rewrite('moscow & hotel', 'select keyword, sample from test_tsquery'::text );
 select rewrite('bar &  new & qq & foo & york', 'select keyword, sample from test_tsquery'::text );
 
+select rewrite( ARRAY['moscow', keyword, sample] ) from test_tsquery;
+select rewrite( ARRAY['moscow & hotel', keyword, sample] ) from test_tsquery;
+select rewrite( ARRAY['bar &  new & qq & foo & york', keyword, sample] ) from test_tsquery;
+
+
 select keyword from test_tsquery where keyword @> 'new';
 select keyword from test_tsquery where keyword @> 'moscow';
 select keyword from test_tsquery where keyword <@ 'new';
 select keyword from test_tsquery where keyword <@ 'moscow';
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where keyword <@ query;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where keyword <@ query;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where keyword <@ query;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where query @> keyword;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where query @> keyword;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where query @> keyword;
 
 create index qq on test_tsquery using gist (keyword gist_tp_tsquery_ops);
 set enable_seqscan='off';
@@ -128,7 +139,12 @@ select keyword from test_tsquery where keyword @> 'new';
 select keyword from test_tsquery where keyword @> 'moscow';
 select keyword from test_tsquery where keyword <@ 'new';
 select keyword from test_tsquery where keyword <@ 'moscow';
-
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where keyword <@ query;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where keyword <@ query;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where keyword <@ query;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow') as query where query @> keyword;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'moscow & hotel') as query where query @> keyword;
+select rewrite( ARRAY[query, keyword, sample] ) from test_tsquery, to_tsquery('english', 'bar &  new & qq & foo & york') as query where query @> keyword;
 set enable_seqscan='on';
 
 
index 0a1207295f8d11308a709802e1b61536a776717d..e6546e3e6cd10d1f9ae3b0e069b6017f18a159b2 100644 (file)
@@ -14,6 +14,7 @@
 #include "postgres.h"
 
 #include "catalog/namespace.h"
+#include "catalog/pg_type.h"
 #include "commands/trigger.h"
 #include "fmgr.h"
 #include "tsearch/ts_utils.h"
@@ -77,13 +78,14 @@ Datum tsa_set_curprs_byname(PG_FUNCTION_ARGS);
 Datum tsa_parse_current(PG_FUNCTION_ARGS);
 Datum tsa_set_curcfg(PG_FUNCTION_ARGS);
 Datum tsa_set_curcfg_byname(PG_FUNCTION_ARGS);
-Datum tsa_show_curcfg(PG_FUNCTION_ARGS);
 Datum tsa_to_tsvector_name(PG_FUNCTION_ARGS);
 Datum tsa_to_tsquery_name(PG_FUNCTION_ARGS);
 Datum tsa_plainto_tsquery_name(PG_FUNCTION_ARGS);
 Datum tsa_headline_byname(PG_FUNCTION_ARGS);
 Datum tsa_ts_stat(PG_FUNCTION_ARGS);
 Datum tsa_tsearch2(PG_FUNCTION_ARGS);
+Datum tsa_rewrite_accum(PG_FUNCTION_ARGS);
+Datum tsa_rewrite_finish(PG_FUNCTION_ARGS);
 
 PG_FUNCTION_INFO_V1(tsa_lexize_byname);
 PG_FUNCTION_INFO_V1(tsa_lexize_bycurrent);
@@ -95,13 +97,14 @@ PG_FUNCTION_INFO_V1(tsa_set_curprs_byname);
 PG_FUNCTION_INFO_V1(tsa_parse_current);
 PG_FUNCTION_INFO_V1(tsa_set_curcfg);
 PG_FUNCTION_INFO_V1(tsa_set_curcfg_byname);
-PG_FUNCTION_INFO_V1(tsa_show_curcfg);
 PG_FUNCTION_INFO_V1(tsa_to_tsvector_name);
 PG_FUNCTION_INFO_V1(tsa_to_tsquery_name);
 PG_FUNCTION_INFO_V1(tsa_plainto_tsquery_name);
 PG_FUNCTION_INFO_V1(tsa_headline_byname);
 PG_FUNCTION_INFO_V1(tsa_ts_stat);
 PG_FUNCTION_INFO_V1(tsa_tsearch2);
+PG_FUNCTION_INFO_V1(tsa_rewrite_accum);
+PG_FUNCTION_INFO_V1(tsa_rewrite_finish);
 
 
 /*
@@ -138,9 +141,6 @@ UNSUPPORTED_FUNCTION(tsa_prsd_headline);
 UNSUPPORTED_FUNCTION(tsa_reset_tsearch);
 UNSUPPORTED_FUNCTION(tsa_get_covers);
 
-UNSUPPORTED_FUNCTION(tsa_rewrite_accum);
-UNSUPPORTED_FUNCTION(tsa_rewrite_finish);
-
 
 /*
  * list of redefined functions
@@ -275,6 +275,7 @@ tsa_set_curcfg_byname(PG_FUNCTION_ARGS)
        char *name;
 
        name = TextPGetCString(arg0);
+
        set_config_option("default_text_search_config", name,
                                          PGC_USERSET,
                                          PGC_S_SESSION,
@@ -284,20 +285,6 @@ tsa_set_curcfg_byname(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
-/* show_curcfg() */
-Datum
-tsa_show_curcfg(PG_FUNCTION_ARGS)
-{
-       char *cfgname;
-       Oid config_oid;
-
-       cfgname = GetConfigOptionByName("default_text_search_config", NULL);
-       config_oid = DatumGetObjectId(DirectFunctionCall1(regconfigin,
-                                                                                                         CStringGetDatum(cfgname)));
-
-       PG_RETURN_OID(config_oid);
-}
-
 /* to_tsvector(text, text) */
 Datum
 tsa_to_tsvector_name(PG_FUNCTION_ARGS)
@@ -411,6 +398,136 @@ tsa_tsearch2(PG_FUNCTION_ARGS)
        return tsvector_update_trigger_byid(fcinfo);
 }
 
+
+Datum
+tsa_rewrite_accum(PG_FUNCTION_ARGS)
+{
+       TSQuery         acc;
+       ArrayType  *qa;
+       TSQuery         q;
+       QTNode     *qex = NULL,
+                          *subs = NULL,
+                          *acctree = NULL;
+       bool            isfind = false;
+       Datum      *elemsp;
+       int                     nelemsp;
+       MemoryContext aggcontext;
+       MemoryContext oldcontext;
+
+       aggcontext = ((AggState *) fcinfo->context)->aggcontext;
+
+       if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
+       {
+               acc = (TSQuery) MemoryContextAlloc(aggcontext, HDRSIZETQ);
+               SET_VARSIZE(acc, HDRSIZETQ);
+               acc->size = 0;
+       }
+       else
+               acc = PG_GETARG_TSQUERY(0);
+
+       if (PG_ARGISNULL(1) || PG_GETARG_POINTER(1) == NULL)
+               PG_RETURN_TSQUERY(acc);
+       else
+               qa = PG_GETARG_ARRAYTYPE_P_COPY(1);
+
+       if (ARR_NDIM(qa) != 1)
+               elog(ERROR, "array must be one-dimensional, not %d dimensions",
+                        ARR_NDIM(qa));
+       if (ArrayGetNItems(ARR_NDIM(qa), ARR_DIMS(qa)) != 3)
+               elog(ERROR, "array must have three elements");
+       if (ARR_ELEMTYPE(qa) != TSQUERYOID)
+               elog(ERROR, "array must contain tsquery elements");
+
+       deconstruct_array(qa, TSQUERYOID, -1, false, 'i', &elemsp, NULL, &nelemsp);
+
+       q = DatumGetTSQuery(elemsp[0]);
+       if (q->size == 0)
+       {
+               pfree(elemsp);
+               PG_RETURN_POINTER(acc);
+       }
+
+       if (!acc->size)
+       {
+               if (VARSIZE(acc) > HDRSIZETQ)
+               {
+                       pfree(elemsp);
+                       PG_RETURN_POINTER(acc);
+               }
+               else
+                       acctree = QT2QTN(GETQUERY(q), GETOPERAND(q));
+       }
+       else
+               acctree = QT2QTN(GETQUERY(acc), GETOPERAND(acc));
+
+       QTNTernary(acctree);
+       QTNSort(acctree);
+
+       q = DatumGetTSQuery(elemsp[1]);
+       if (q->size == 0)
+       {
+               pfree(elemsp);
+               PG_RETURN_POINTER(acc);
+       }
+       qex = QT2QTN(GETQUERY(q), GETOPERAND(q));
+       QTNTernary(qex);
+       QTNSort(qex);
+
+       q = DatumGetTSQuery(elemsp[2]);
+       if (q->size)
+               subs = QT2QTN(GETQUERY(q), GETOPERAND(q));
+
+       acctree = findsubquery(acctree, qex, subs, &isfind);
+
+       if (isfind || !acc->size)
+       {
+               /* pfree( acc ); do not pfree(p), because nodeAgg.c will */
+               if (acctree)
+               {
+                       QTNBinary(acctree);
+                       oldcontext = MemoryContextSwitchTo(aggcontext);
+                       acc = QTN2QT(acctree);
+                       MemoryContextSwitchTo(oldcontext);
+               }
+               else
+               {
+                       acc = (TSQuery) MemoryContextAlloc(aggcontext, HDRSIZETQ);
+                       SET_VARSIZE(acc, HDRSIZETQ);
+                       acc->size = 0;
+               }
+       }
+
+       pfree(elemsp);
+       QTNFree(qex);
+       QTNFree(subs);
+       QTNFree(acctree);
+
+       PG_RETURN_TSQUERY(acc);
+}
+
+Datum
+tsa_rewrite_finish(PG_FUNCTION_ARGS)
+{
+       TSQuery         acc = PG_GETARG_TSQUERY(0);
+       TSQuery         rewrited;
+
+       if (acc == NULL || PG_ARGISNULL(0) || acc->size == 0)
+       {
+               rewrited = (TSQuery) palloc(HDRSIZETQ);
+               SET_VARSIZE(rewrited, HDRSIZETQ);
+               rewrited->size = 0;
+       }
+       else
+       {
+               rewrited = (TSQuery) palloc(VARSIZE(acc));
+               memcpy(rewrited, acc, VARSIZE(acc));
+               pfree(acc);
+       }
+
+       PG_RETURN_POINTER(rewrited);
+}
+
+
 /*
  * Get Oid of current dictionary
  */
index 519accff6abbb719daecd13c47d23d6111f33d8d..958a3d9e17e2c30d683458dbfbae0f0ad44b3c18 100644 (file)
@@ -206,9 +206,9 @@ CREATE FUNCTION set_curcfg(text)
 
 CREATE FUNCTION show_curcfg()
        RETURNS oid
-       as 'MODULE_PATHNAME', 'tsa_show_curcfg'
-       LANGUAGE C
-       RETURNS NULL ON NULL INPUT;
+       AS 'get_current_ts_config'
+       LANGUAGE INTERNAL
+       RETURNS NULL ON NULL INPUT STABLE;
 
 CREATE FUNCTION length(tsvector)
        RETURNS int4
index 4d1b6223a5db6d56280ba91be6232e3a817dec2f..48268e552eb683699450ffecb3cdb39e9100a11d 100644 (file)
@@ -233,7 +233,7 @@ dropvoidsubtree(QTNode * root)
        return root;
 }
 
-static QTNode *
+QTNode *
 findsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind)
 {
        bool            DidFind = false;
index debd360dec5a3a4ec17316fd6dd8c3c2e39a1bdd..fdc54a2577d6df9cba869101d8dcff82c3a95c99 100644 (file)
@@ -193,6 +193,8 @@ extern QTNode *QTNCopy(QTNode *in);
 extern void QTNClearFlags(QTNode *in, uint32 flags);
 extern bool QTNEq(QTNode * a, QTNode * b);
 extern TSQuerySign makeTSQuerySign(TSQuery a);
+extern QTNode *findsubquery(QTNode *root, QTNode *ex, QTNode *subs,
+                                                       bool *isfind);
 
 /*
  * TSQuery GiST support