From 4394c1b09c0e85984668d60428acb8f0590cbf42 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 13 Nov 2007 22:14:50 +0000 Subject: [PATCH] Resurrect the code for the rewrite(ARRAY[...]) aggregate function, and put it into contrib/tsearch2 compatibility module. --- contrib/tsearch2/expected/tsearch2.out | 90 ++++++++++++++ contrib/tsearch2/sql/tsearch2.sql | 18 ++- contrib/tsearch2/tsearch2.c | 157 +++++++++++++++++++++--- contrib/tsearch2/tsearch2.sql.in | 8 +- src/backend/utils/adt/tsquery_rewrite.c | 4 +- src/include/tsearch/ts_utils.h | 4 +- 6 files changed, 253 insertions(+), 28 deletions(-) diff --git a/contrib/tsearch2/expected/tsearch2.out b/contrib/tsearch2/expected/tsearch2.out index d4a81f69cb..6fb820c3cf 100644 --- a/contrib/tsearch2/expected/tsearch2.out +++ b/contrib/tsearch2/expected/tsearch2.out @@ -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 diff --git a/contrib/tsearch2/sql/tsearch2.sql b/contrib/tsearch2/sql/tsearch2.sql index a7f8e8d267..b20055c45c 100644 --- a/contrib/tsearch2/sql/tsearch2.sql +++ b/contrib/tsearch2/sql/tsearch2.sql @@ -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'; diff --git a/contrib/tsearch2/tsearch2.c b/contrib/tsearch2/tsearch2.c index d51ba7ede7..25fb697529 100644 --- a/contrib/tsearch2/tsearch2.c +++ b/contrib/tsearch2/tsearch2.c @@ -7,13 +7,14 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.c,v 1.1 2007/11/13 21:02:29 tgl Exp $ + * $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.c,v 1.2 2007/11/13 22:14:50 tgl Exp $ * *------------------------------------------------------------------------- */ #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 */ diff --git a/contrib/tsearch2/tsearch2.sql.in b/contrib/tsearch2/tsearch2.sql.in index 80d9cb3e42..82c6163481 100644 --- a/contrib/tsearch2/tsearch2.sql.in +++ b/contrib/tsearch2/tsearch2.sql.in @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.sql.in,v 1.1 2007/11/13 21:02:29 tgl Exp $ */ +/* $PostgreSQL: pgsql/contrib/tsearch2/tsearch2.sql.in,v 1.2 2007/11/13 22:14:50 tgl Exp $ */ -- Adjust this setting to control where the objects get created. SET search_path = public; @@ -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 diff --git a/src/backend/utils/adt/tsquery_rewrite.c b/src/backend/utils/adt/tsquery_rewrite.c index f7a335b337..51f05a0d69 100644 --- a/src/backend/utils/adt/tsquery_rewrite.c +++ b/src/backend/utils/adt/tsquery_rewrite.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.7 2007/10/24 03:30:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.8 2007/11/13 22:14:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -233,7 +233,7 @@ dropvoidsubtree(QTNode * root) return root; } -static QTNode * +QTNode * findsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind) { bool DidFind = false; diff --git a/src/include/tsearch/ts_utils.h b/src/include/tsearch/ts_utils.h index 48dc90eaee..575cf75953 100644 --- a/src/include/tsearch/ts_utils.h +++ b/src/include/tsearch/ts_utils.h @@ -5,7 +5,7 @@ * * Copyright (c) 1998-2007, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/tsearch/ts_utils.h,v 1.7 2007/10/23 01:44:39 tgl Exp $ + * $PostgreSQL: pgsql/src/include/tsearch/ts_utils.h,v 1.8 2007/11/13 22:14:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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 -- 2.40.0