From 553bc4163388d660a30d5cb0cacad0e86fb7e449 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Mon, 31 May 2004 16:51:56 +0000 Subject: [PATCH] 1 add namespaces as Tom suggest http://www.pgsql.ru/db/mw/msg.html?mid=1987703 2 remove select qeury in inserts --- contrib/tsearch2/common.c | 62 +++++++++++++++++++++++ contrib/tsearch2/common.h | 9 ++++ contrib/tsearch2/dict.c | 49 ++++++++++--------- contrib/tsearch2/query.c | 10 +++- contrib/tsearch2/snmap.c | 9 +++- contrib/tsearch2/snmap.h | 1 + contrib/tsearch2/ts_cfg.c | 81 ++++++++++++++++++------------- contrib/tsearch2/tsearch.sql.in | 30 ++++++------ contrib/tsearch2/tsvector.c | 20 ++++++-- contrib/tsearch2/untsearch.sql.in | 6 +-- contrib/tsearch2/wparser.c | 65 ++++++++++++++----------- 11 files changed, 231 insertions(+), 111 deletions(-) diff --git a/contrib/tsearch2/common.c b/contrib/tsearch2/common.c index 3006218007..b51c3e0583 100644 --- a/contrib/tsearch2/common.c +++ b/contrib/tsearch2/common.c @@ -1,9 +1,29 @@ #include "postgres.h" + +#include "postgres.h" +#include "fmgr.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_namespace.h" +#include "utils/syscache.h" + +#include "ts_cfg.h" +#include "dict.h" +#include "wparser.h" +#include "snmap.h" +#include "common.h" +#include "tsvector.h" + + + #include "common.h" #include "wparser.h" #include "ts_cfg.h" #include "dict.h" + +Oid TSNSP_FunctionOid = InvalidOid; + + text * char2text(char *in) { @@ -100,3 +120,45 @@ text_cmp(text *a, text *b) return (int) VARSIZE(a) - (int) VARSIZE(b); } + +char* +get_namespace(Oid funcoid) { + HeapTuple tuple; + Form_pg_proc proc; + Form_pg_namespace nsp; + Oid nspoid; + char *txt; + + tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for proc oid %u", funcoid); + proc=(Form_pg_proc) GETSTRUCT(tuple); + nspoid = proc->pronamespace; + ReleaseSysCache(tuple); + + tuple = SearchSysCache(NAMESPACEOID, ObjectIdGetDatum(nspoid), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for namespace oid %u", nspoid); + nsp = (Form_pg_namespace) GETSTRUCT(tuple); + txt = pstrdup( NameStr((nsp->nspname)) ); + ReleaseSysCache(tuple); + + return txt; +} + +Oid +get_oidnamespace(Oid funcoid) { + HeapTuple tuple; + Form_pg_proc proc; + Oid nspoid; + + tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcoid), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for proc oid %u", funcoid); + proc=(Form_pg_proc) GETSTRUCT(tuple); + nspoid = proc->pronamespace; + ReleaseSysCache(tuple); + + return nspoid; +} + diff --git a/contrib/tsearch2/common.h b/contrib/tsearch2/common.h index 481f00405b..6720598f81 100644 --- a/contrib/tsearch2/common.h +++ b/contrib/tsearch2/common.h @@ -21,4 +21,13 @@ int text_cmp(text *a, text *b); void ts_error(int state, const char *format,...); +extern Oid TSNSP_FunctionOid; /* oid of called function, needed only for determ namespace, no more */ +char* get_namespace(Oid funcoid); +Oid get_oidnamespace(Oid funcoid); + +#define SET_FUNCOID() do { \ + if ( fcinfo->flinfo && fcinfo->flinfo->fn_oid != InvalidOid ) \ + TSNSP_FunctionOid = fcinfo->flinfo->fn_oid; \ +} while(0) + #endif diff --git a/contrib/tsearch2/dict.c b/contrib/tsearch2/dict.c index 8bfeb96de2..7be406da9e 100644 --- a/contrib/tsearch2/dict.c +++ b/contrib/tsearch2/dict.c @@ -19,8 +19,6 @@ /*********top interface**********/ -static void *plan_getdict = NULL; - void init_dict(Oid id, DictInfo * dict) { @@ -28,20 +26,22 @@ init_dict(Oid id, DictInfo * dict) bool isnull; Datum pars[1]; int stat; + void *plan; + char buf[1024]; + char *nsp = get_namespace(TSNSP_FunctionOid); arg[0] = OIDOID; pars[0] = ObjectIdGetDatum(id); memset(dict, 0, sizeof(DictInfo)); SPI_connect(); - if (!plan_getdict) - { - plan_getdict = SPI_saveplan(SPI_prepare("select dict_init, dict_initoption, dict_lexize from pg_ts_dict where oid = $1", 1, arg)); - if (!plan_getdict) - ts_error(ERROR, "SPI_prepare() failed"); - } + sprintf(buf,"select dict_init, dict_initoption, dict_lexize from %s.pg_ts_dict where oid = $1", nsp); + pfree(nsp); + plan= SPI_prepare(buf, 1, arg); + if (!plan) + ts_error(ERROR, "SPI_prepare() failed"); - stat = SPI_execp(plan_getdict, pars, " ", 1); + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed > 0) @@ -63,6 +63,7 @@ init_dict(Oid id, DictInfo * dict) } else ts_error(ERROR, "No dictionary with id %d", id); + SPI_freeplan(plan); SPI_finish(); } @@ -133,8 +134,6 @@ finddict(Oid id) return finddict(id); /* qsort changed order!! */ ; } -static void *plan_name2id = NULL; - Oid name2id_dict(text *name) { @@ -143,6 +142,8 @@ name2id_dict(text *name) Datum pars[1]; int stat; Oid id = findSNMap_t(&(DList.name2id_map), name); + void *plan; + char buf[1024], *nsp; arg[0] = TEXTOID; pars[0] = PointerGetDatum(name); @@ -150,21 +151,22 @@ name2id_dict(text *name) if (id) return id; + nsp = get_namespace(TSNSP_FunctionOid); SPI_connect(); - if (!plan_name2id) - { - plan_name2id = SPI_saveplan(SPI_prepare("select oid from pg_ts_dict where dict_name = $1", 1, arg)); - if (!plan_name2id) - ts_error(ERROR, "SPI_prepare() failed"); - } + sprintf(buf,"select oid from %s.pg_ts_dict where dict_name = $1", nsp); + pfree(nsp); + plan= SPI_prepare(buf, 1, arg); + if (!plan) + ts_error(ERROR, "SPI_prepare() failed"); - stat = SPI_execp(plan_name2id, pars, " ", 1); + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed > 0) id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); else ts_error(ERROR, "No dictionary with name '%s'", text2char(name)); + SPI_freeplan(plan); SPI_finish(); addSNMap_t(&(DList.name2id_map), name, id); return id; @@ -179,12 +181,14 @@ Datum lexize(PG_FUNCTION_ARGS) { text *in = PG_GETARG_TEXT_P(1); - DictInfo *dict = finddict(PG_GETARG_OID(0)); + DictInfo *dict; char **res, **ptr; Datum *da; ArrayType *a; + SET_FUNCOID(); + dict = finddict(PG_GETARG_OID(0)); ptr = res = (char **) DatumGetPointer( FunctionCall3(&(dict->lexize_info), @@ -241,8 +245,8 @@ lexize_byname(PG_FUNCTION_ARGS) { text *dictname = PG_GETARG_TEXT_P(0); Datum res; + SET_FUNCOID(); - strdup("simple"); res = DirectFunctionCall3( lexize, ObjectIdGetDatum(name2id_dict(dictname)), @@ -263,6 +267,7 @@ Datum set_curdict(PG_FUNCTION_ARGS); Datum set_curdict(PG_FUNCTION_ARGS) { + SET_FUNCOID(); finddict(PG_GETARG_OID(0)); currect_dictionary_id = PG_GETARG_OID(0); PG_RETURN_VOID(); @@ -274,7 +279,7 @@ Datum set_curdict_byname(PG_FUNCTION_ARGS) { text *dictname = PG_GETARG_TEXT_P(0); - + SET_FUNCOID(); DirectFunctionCall1( set_curdict, ObjectIdGetDatum(name2id_dict(dictname)) @@ -289,7 +294,7 @@ Datum lexize_bycurrent(PG_FUNCTION_ARGS) { Datum res; - + SET_FUNCOID(); if (currect_dictionary_id == 0) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), diff --git a/contrib/tsearch2/query.c b/contrib/tsearch2/query.c index 1cdefa76d8..81343b0c46 100644 --- a/contrib/tsearch2/query.c +++ b/contrib/tsearch2/query.c @@ -469,6 +469,7 @@ TS_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void * Datum rexectsq(PG_FUNCTION_ARGS) { + SET_FUNCOID(); return DirectFunctionCall2( exectsq, PG_GETARG_DATUM(1), @@ -483,7 +484,7 @@ exectsq(PG_FUNCTION_ARGS) QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1))); CHKVAL chkval; bool result; - + SET_FUNCOID(); if (!val->size || !query->size) { PG_FREE_IF_COPY(val, 0); @@ -638,6 +639,7 @@ static QUERYTYPE * Datum tsquery_in(PG_FUNCTION_ARGS) { + SET_FUNCOID(); PG_RETURN_POINTER(queryin((char *) PG_GETARG_POINTER(0), pushval_asis, 0)); } @@ -863,6 +865,7 @@ to_tsquery(PG_FUNCTION_ARGS) QUERYTYPE *query; ITEM *res; int4 len; + SET_FUNCOID(); str = text2char(in); PG_FREE_IF_COPY(in, 1); @@ -884,7 +887,9 @@ Datum to_tsquery_name(PG_FUNCTION_ARGS) { text *name = PG_GETARG_TEXT_P(0); - Datum res = DirectFunctionCall2(to_tsquery, + Datum res; + SET_FUNCOID(); + res = DirectFunctionCall2(to_tsquery, Int32GetDatum(name2id_cfg(name)), PG_GETARG_DATUM(1)); @@ -895,6 +900,7 @@ to_tsquery_name(PG_FUNCTION_ARGS) Datum to_tsquery_current(PG_FUNCTION_ARGS) { + SET_FUNCOID(); PG_RETURN_DATUM(DirectFunctionCall2(to_tsquery, Int32GetDatum(get_currcfg()), PG_GETARG_DATUM(0))); diff --git a/contrib/tsearch2/snmap.c b/contrib/tsearch2/snmap.c index ec7ef69a79..d41fb45b0d 100644 --- a/contrib/tsearch2/snmap.c +++ b/contrib/tsearch2/snmap.c @@ -13,7 +13,12 @@ static int compareSNMapEntry(const void *a, const void *b) { - return strcmp(((SNMapEntry *) a)->key, ((SNMapEntry *) b)->key); + if ( ((SNMapEntry *) a)->nsp < ((SNMapEntry *) b)->nsp ) + return -1; + else if ( ((SNMapEntry *) a)->nsp > ((SNMapEntry *) b)->nsp ) + return 1; + else + return strcmp(((SNMapEntry *) a)->key, ((SNMapEntry *) b)->key); } void @@ -37,6 +42,7 @@ addSNMap(SNMap * map, char *key, Oid value) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); + map->list[map->len].nsp = get_oidnamespace(TSNSP_FunctionOid); map->list[map->len].value = value; map->len++; if (map->len > 1) @@ -59,6 +65,7 @@ findSNMap(SNMap * map, char *key) SNMapEntry ks; ks.key = key; + ks.nsp = get_oidnamespace(TSNSP_FunctionOid); ks.value = 0; if (map->len == 0 || !map->list) diff --git a/contrib/tsearch2/snmap.h b/contrib/tsearch2/snmap.h index ae188b66a4..c3e80fca57 100644 --- a/contrib/tsearch2/snmap.h +++ b/contrib/tsearch2/snmap.h @@ -7,6 +7,7 @@ typedef struct { char *key; Oid value; + Oid nsp; } SNMapEntry; typedef struct diff --git a/contrib/tsearch2/ts_cfg.c b/contrib/tsearch2/ts_cfg.c index ded92ac1bc..efd79a1e32 100644 --- a/contrib/tsearch2/ts_cfg.c +++ b/contrib/tsearch2/ts_cfg.c @@ -25,10 +25,6 @@ /*********top interface**********/ -static void *plan_getcfg_bylocale = NULL; -static void *plan_getcfg = NULL; -static void *plan_getmap = NULL; -static void *plan_name2id = NULL; static Oid current_cfg_id = 0; void @@ -42,7 +38,10 @@ init_cfg(Oid id, TSCfgInfo * cfg) j; text *ptr; text *prsname = NULL; + char *nsp=get_namespace(TSNSP_FunctionOid); + char buf[1024]; MemoryContext oldcontext; + void *plan; arg[0] = OIDOID; arg[1] = OIDOID; @@ -51,14 +50,13 @@ init_cfg(Oid id, TSCfgInfo * cfg) memset(cfg, 0, sizeof(TSCfgInfo)); SPI_connect(); - if (!plan_getcfg) - { - plan_getcfg = SPI_saveplan(SPI_prepare("select prs_name from pg_ts_cfg where oid = $1", 1, arg)); - if (!plan_getcfg) - ts_error(ERROR, "SPI_prepare() failed"); - } - stat = SPI_execp(plan_getcfg, pars, " ", 1); + sprintf(buf, "select prs_name from %s.pg_ts_cfg where oid = $1", nsp); + plan= SPI_prepare(buf, 1, arg); + if (!plan) + ts_error(ERROR, "SPI_prepare() failed"); + + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed > 0) @@ -75,16 +73,16 @@ init_cfg(Oid id, TSCfgInfo * cfg) else ts_error(ERROR, "No tsearch cfg with id %d", id); + SPI_freeplan(plan); + arg[0] = TEXTOID; - if (!plan_getmap) - { - plan_getmap = SPI_saveplan(SPI_prepare("select lt.tokid, pg_ts_cfgmap.dict_name from pg_ts_cfgmap, pg_ts_cfg, token_type( $1 ) as lt where lt.alias = pg_ts_cfgmap.tok_alias and pg_ts_cfgmap.ts_name = pg_ts_cfg.ts_name and pg_ts_cfg.oid= $2 order by lt.tokid desc;", 2, arg)); - if (!plan_getmap) - ts_error(ERROR, "SPI_prepare() failed"); - } + sprintf(buf, "select lt.tokid, map.dict_name from %s.pg_ts_cfgmap as map, %s.pg_ts_cfg as cfg, %s.token_type( $1 ) as lt where lt.alias = map.tok_alias and map.ts_name = cfg.ts_name and cfg.oid= $2 order by lt.tokid desc;", nsp, nsp, nsp); + plan= SPI_prepare(buf, 2, arg); + if (!plan) + ts_error(ERROR, "SPI_prepare() failed"); pars[0] = PointerGetDatum(prsname); - stat = SPI_execp(plan_getmap, pars, " ", 0); + stat = SPI_execp(plan, pars, " ", 0); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed <= 0) @@ -136,9 +134,11 @@ init_cfg(Oid id, TSCfgInfo * cfg) pfree(a); } + SPI_freeplan(plan); SPI_finish(); cfg->prs_id = name2id_prs(prsname); pfree(prsname); + pfree(nsp); for (i = 0; i < cfg->len; i++) { for (j = 0; j < cfg->map[i].len; j++) @@ -235,6 +235,9 @@ name2id_cfg(text *name) Datum pars[1]; int stat; Oid id = findSNMap_t(&(CList.name2id_map), name); + void *plan; + char *nsp; + char buf[1024]; arg[0] = TEXTOID; pars[0] = PointerGetDatum(name); @@ -242,16 +245,15 @@ name2id_cfg(text *name) if (id) return id; + nsp=get_namespace(TSNSP_FunctionOid); SPI_connect(); - if (!plan_name2id) - { - plan_name2id = SPI_saveplan(SPI_prepare("select oid from pg_ts_cfg where ts_name = $1", 1, arg)); - if (!plan_name2id) - /* internal error */ - elog(ERROR, "SPI_prepare() failed"); - } + sprintf(buf, "select oid from %s.pg_ts_cfg where ts_name = $1", nsp); + plan= SPI_prepare(buf, 1, arg); + if (!plan) + /* internal error */ + elog(ERROR, "SPI_prepare() failed"); - stat = SPI_execp(plan_name2id, pars, " ", 1); + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) /* internal error */ elog(ERROR, "SPI_execp return %d", stat); @@ -268,6 +270,7 @@ name2id_cfg(text *name) (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("no tsearch config"))); + SPI_freeplan(plan); SPI_finish(); addSNMap_t(&(CList.name2id_map), name, id); return id; @@ -549,22 +552,25 @@ get_currcfg(void) Datum pars[1]; bool isnull; int stat; + char buf[1024]; + char *nsp; + void *plan; if (current_cfg_id > 0) return current_cfg_id; + nsp=get_namespace(TSNSP_FunctionOid); SPI_connect(); - if (!plan_getcfg_bylocale) - { - plan_getcfg_bylocale = SPI_saveplan(SPI_prepare("select oid from pg_ts_cfg where locale = $1 ", 1, arg)); - if (!plan_getcfg_bylocale) - /* internal error */ - elog(ERROR, "SPI_prepare() failed"); - } + sprintf(buf, "select oid from %s.pg_ts_cfg where locale = $1 ", nsp); + pfree(nsp); + plan = SPI_prepare(buf, 1, arg); + if (!plan) + /* internal error */ + elog(ERROR, "SPI_prepare() failed"); curlocale = setlocale(LC_CTYPE, NULL); pars[0] = PointerGetDatum(char2text((char *) curlocale)); - stat = SPI_execp(plan_getcfg_bylocale, pars, " ", 1); + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) /* internal error */ @@ -577,6 +583,7 @@ get_currcfg(void) errmsg("could not find tsearch config by locale"))); pfree(DatumGetPointer(pars[0])); + SPI_freeplan(plan); SPI_finish(); return current_cfg_id; } @@ -586,6 +593,7 @@ Datum set_curcfg(PG_FUNCTION_ARGS); Datum set_curcfg(PG_FUNCTION_ARGS) { + SET_FUNCOID(); findcfg(PG_GETARG_OID(0)); current_cfg_id = PG_GETARG_OID(0); PG_RETURN_VOID(); @@ -597,7 +605,7 @@ Datum set_curcfg_byname(PG_FUNCTION_ARGS) { text *name = PG_GETARG_TEXT_P(0); - + SET_FUNCOID(); DirectFunctionCall1( set_curcfg, ObjectIdGetDatum(name2id_cfg(name)) @@ -611,6 +619,7 @@ Datum show_curcfg(PG_FUNCTION_ARGS); Datum show_curcfg(PG_FUNCTION_ARGS) { + SET_FUNCOID(); PG_RETURN_OID(get_currcfg()); } @@ -619,6 +628,8 @@ Datum reset_tsearch(PG_FUNCTION_ARGS); Datum reset_tsearch(PG_FUNCTION_ARGS) { + SET_FUNCOID(); ts_error(NOTICE, "TSearch cache cleaned"); PG_RETURN_VOID(); } + diff --git a/contrib/tsearch2/tsearch.sql.in b/contrib/tsearch2/tsearch.sql.in index 1f8ed4b1d8..25cb05f59c 100644 --- a/contrib/tsearch2/tsearch.sql.in +++ b/contrib/tsearch2/tsearch.sql.in @@ -57,9 +57,9 @@ CREATE FUNCTION dex_lexize(internal,internal,int4) insert into pg_ts_dict select 'simple', - (select oid from pg_proc where proname='dex_init'), + 'dex_init(text)', null, - (select oid from pg_proc where proname='dex_lexize'), + 'dex_lexize(internal,internal,int4)', 'Simple example of dictionary.' ; @@ -76,9 +76,9 @@ CREATE FUNCTION snb_lexize(internal,internal,int4) insert into pg_ts_dict select 'en_stem', - (select oid from pg_proc where proname='snb_en_init'), + 'snb_en_init(text)', 'DATA_PATH/english.stop', - (select oid from pg_proc where proname='snb_lexize'), + 'snb_lexize(internal,internal,int4)', 'English Stemmer. Snowball.' ; @@ -89,9 +89,9 @@ CREATE FUNCTION snb_ru_init(text) insert into pg_ts_dict select 'ru_stem', - (select oid from pg_proc where proname='snb_ru_init'), + 'snb_ru_init(text)', 'DATA_PATH/russian.stop', - (select oid from pg_proc where proname='snb_lexize'), + 'snb_lexize(internal,internal,int4)', 'Russian Stemmer. Snowball.' ; @@ -108,9 +108,9 @@ CREATE FUNCTION spell_lexize(internal,internal,int4) insert into pg_ts_dict select 'ispell_template', - (select oid from pg_proc where proname='spell_init'), + 'spell_init(text)', null, - (select oid from pg_proc where proname='spell_lexize'), + 'spell_lexize(internal,internal,int4)', 'ISpell interface. Must have .dict and .aff files' ; @@ -127,9 +127,9 @@ CREATE FUNCTION syn_lexize(internal,internal,int4) insert into pg_ts_dict select 'synonym', - (select oid from pg_proc where proname='syn_init'), + 'syn_init(text)', null, - (select oid from pg_proc where proname='syn_lexize'), + 'syn_lexize(internal,internal,int4)', 'Example of synonym dictionary' ; @@ -227,11 +227,11 @@ CREATE FUNCTION prsd_headline(internal,internal,internal) insert into pg_ts_parser select 'default', - (select oid from pg_proc where proname='prsd_start'), - (select oid from pg_proc where proname='prsd_getlexeme'), - (select oid from pg_proc where proname='prsd_end'), - (select oid from pg_proc where proname='prsd_headline'), - (select oid from pg_proc where proname='prsd_lextype'), + 'prsd_start(internal,int4)', + 'prsd_getlexeme(internal,internal,internal)', + 'prsd_end(internal)', + 'prsd_headline(internal,internal,internal)', + 'prsd_lextype(internal)', 'Parser from OpenFTS v0.34' ; diff --git a/contrib/tsearch2/tsvector.c b/contrib/tsearch2/tsvector.c index 14bdd9ff5c..a39a40fb36 100644 --- a/contrib/tsearch2/tsvector.c +++ b/contrib/tsearch2/tsvector.c @@ -404,7 +404,7 @@ tsvector_in(PG_FUNCTION_ARGS) *cur; int4 i, buflen = 256; - + SET_FUNCOID(); state.prsbuf = buf; state.len = 32; state.word = (char *) palloc(state.len); @@ -723,7 +723,10 @@ to_tsvector(PG_FUNCTION_ARGS) text *in = PG_GETARG_TEXT_P(1); PRSTEXT prs; tsvector *out = NULL; - TSCfgInfo *cfg = findcfg(PG_GETARG_INT32(0)); + TSCfgInfo *cfg; + + SET_FUNCOID(); + cfg = findcfg(PG_GETARG_INT32(0)); prs.lenwords = 32; prs.curwords = 0; @@ -749,7 +752,9 @@ Datum to_tsvector_name(PG_FUNCTION_ARGS) { text *cfg = PG_GETARG_TEXT_P(0); - Datum res = DirectFunctionCall3( + Datum res; + SET_FUNCOID(); + res = DirectFunctionCall3( to_tsvector, Int32GetDatum(name2id_cfg(cfg)), PG_GETARG_DATUM(1), @@ -763,7 +768,9 @@ to_tsvector_name(PG_FUNCTION_ARGS) Datum to_tsvector_current(PG_FUNCTION_ARGS) { - Datum res = DirectFunctionCall3( + Datum res; + SET_FUNCOID(); + res = DirectFunctionCall3( to_tsvector, Int32GetDatum(get_currcfg()), PG_GETARG_DATUM(0), @@ -809,12 +816,15 @@ tsearch2(PG_FUNCTION_ARGS) Trigger *trigger; Relation rel; HeapTuple rettuple = NULL; - TSCfgInfo *cfg = findcfg(get_currcfg()); int numidxattr, i; PRSTEXT prs; Datum datum = (Datum) 0; Oid funcoid = InvalidOid; + TSCfgInfo *cfg; + + SET_FUNCOID(); + cfg = findcfg(get_currcfg()); if (!CALLED_AS_TRIGGER(fcinfo)) /* internal error */ diff --git a/contrib/tsearch2/untsearch.sql.in b/contrib/tsearch2/untsearch.sql.in index b55e3185ab..b1883d5fbd 100644 --- a/contrib/tsearch2/untsearch.sql.in +++ b/contrib/tsearch2/untsearch.sql.in @@ -12,7 +12,7 @@ DROP OPERATOR || (tsvector, tsvector); DROP OPERATOR @@ (tsvector, tsquery); DROP OPERATOR @@ (tsquery, tsvector); -DROP AGGREGATE stat(tsvector); +--DROP AGGREGATE stat(tsvector); DROP TABLE pg_ts_dict; DROP TABLE pg_ts_parser; @@ -24,7 +24,7 @@ DROP TYPE tokenout CASCADE; DROP TYPE tsvector CASCADE; DROP TYPE tsquery CASCADE; DROP TYPE gtsvector CASCADE; -DROP TYPE tsstat CASCADE; +--DROP TYPE tsstat CASCADE; DROP TYPE statinfo CASCADE; DROP TYPE tsdebug CASCADE; @@ -59,8 +59,6 @@ DROP FUNCTION gtsvector_penalty(internal,internal,internal); DROP FUNCTION gtsvector_picksplit(internal, internal); DROP FUNCTION gtsvector_union(internal, internal); DROP FUNCTION reset_tsearch(); -DROP FUNCTION stat(text); -DROP FUNCTION stat(text,stat); DROP FUNCTION tsearch2() CASCADE; DROP FUNCTION _get_parser_from_curcfg(); diff --git a/contrib/tsearch2/wparser.c b/contrib/tsearch2/wparser.c index b97b158ca7..eba2cd6eb5 100644 --- a/contrib/tsearch2/wparser.c +++ b/contrib/tsearch2/wparser.c @@ -21,7 +21,6 @@ /*********top interface**********/ -static void *plan_getparser = NULL; static Oid current_parser_id = InvalidOid; void @@ -31,20 +30,22 @@ init_prs(Oid id, WParserInfo * prs) bool isnull; Datum pars[1]; int stat; + void *plan; + char buf[1024], *nsp; arg[0] = OIDOID; pars[0] = ObjectIdGetDatum(id); memset(prs, 0, sizeof(WParserInfo)); SPI_connect(); - if (!plan_getparser) - { - plan_getparser = SPI_saveplan(SPI_prepare("select prs_start, prs_nexttoken, prs_end, prs_lextype, prs_headline from pg_ts_parser where oid = $1", 1, arg)); - if (!plan_getparser) - ts_error(ERROR, "SPI_prepare() failed"); - } + nsp=get_namespace(TSNSP_FunctionOid); + sprintf(buf, "select prs_start, prs_nexttoken, prs_end, prs_lextype, prs_headline from %s.pg_ts_parser where oid = $1", nsp); + pfree(nsp); + plan= SPI_prepare(buf, 1, arg); + if (!plan) + ts_error(ERROR, "SPI_prepare() failed"); - stat = SPI_execp(plan_getparser, pars, " ", 1); + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed > 0) @@ -64,6 +65,7 @@ init_prs(Oid id, WParserInfo * prs) } else ts_error(ERROR, "No parser with id %d", id); + SPI_freeplan(plan); SPI_finish(); } @@ -130,8 +132,6 @@ findprs(Oid id) return findprs(id); /* qsort changed order!! */ ; } -static void *plan_name2id = NULL; - Oid name2id_prs(text *name) { @@ -140,6 +140,8 @@ name2id_prs(text *name) Datum pars[1]; int stat; Oid id = findSNMap_t(&(PList.name2id_map), name); + char buf[1024], *nsp; + void *plan; arg[0] = TEXTOID; pars[0] = PointerGetDatum(name); @@ -148,20 +150,21 @@ name2id_prs(text *name) return id; SPI_connect(); - if (!plan_name2id) - { - plan_name2id = SPI_saveplan(SPI_prepare("select oid from pg_ts_parser where prs_name = $1", 1, arg)); - if (!plan_name2id) - ts_error(ERROR, "SPI_prepare() failed"); - } + nsp = get_namespace(TSNSP_FunctionOid); + sprintf(buf, "select oid from %s.pg_ts_parser where prs_name = $1", nsp); + pfree(nsp); + plan= SPI_prepare(buf, 1, arg); + if (!plan) + ts_error(ERROR, "SPI_prepare() failed"); - stat = SPI_execp(plan_name2id, pars, " ", 1); + stat = SPI_execp(plan, pars, " ", 1); if (stat < 0) ts_error(ERROR, "SPI_execp return %d", stat); if (SPI_processed > 0) id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); else ts_error(ERROR, "No parser '%s'", text2char(name)); + SPI_freeplan(plan); SPI_finish(); addSNMap_t(&(PList.name2id_map), name, id); return id; @@ -239,7 +242,7 @@ token_type(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; - + SET_FUNCOID(); if (SRF_IS_FIRSTCALL()) { funcctx = SRF_FIRSTCALL_INIT(); @@ -260,7 +263,7 @@ token_type_byname(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; - + SET_FUNCOID(); if (SRF_IS_FIRSTCALL()) { text *name = PG_GETARG_TEXT_P(0); @@ -284,7 +287,7 @@ token_type_current(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; - + SET_FUNCOID(); if (SRF_IS_FIRSTCALL()) { funcctx = SRF_FIRSTCALL_INIT(); @@ -306,6 +309,7 @@ Datum set_curprs(PG_FUNCTION_ARGS); Datum set_curprs(PG_FUNCTION_ARGS) { + SET_FUNCOID(); findprs(PG_GETARG_OID(0)); current_parser_id = PG_GETARG_OID(0); PG_RETURN_VOID(); @@ -317,7 +321,7 @@ Datum set_curprs_byname(PG_FUNCTION_ARGS) { text *name = PG_GETARG_TEXT_P(0); - + SET_FUNCOID(); DirectFunctionCall1( set_curprs, ObjectIdGetDatum(name2id_prs(name)) @@ -440,7 +444,7 @@ parse(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; - + SET_FUNCOID(); if (SRF_IS_FIRSTCALL()) { text *txt = PG_GETARG_TEXT_P(1); @@ -464,7 +468,7 @@ parse_byname(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; - + SET_FUNCOID(); if (SRF_IS_FIRSTCALL()) { text *name = PG_GETARG_TEXT_P(0); @@ -491,7 +495,7 @@ parse_current(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; Datum result; - + SET_FUNCOID(); if (SRF_IS_FIRSTCALL()) { text *txt = PG_GETARG_TEXT_P(0); @@ -515,13 +519,17 @@ Datum headline(PG_FUNCTION_ARGS); Datum headline(PG_FUNCTION_ARGS) { - TSCfgInfo *cfg = findcfg(PG_GETARG_OID(0)); text *in = PG_GETARG_TEXT_P(1); QUERYTYPE *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(2))); text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL; HLPRSTEXT prs; text *out; - WParserInfo *prsobj = findprs(cfg->prs_id); + TSCfgInfo *cfg; + WParserInfo *prsobj; + + SET_FUNCOID(); + cfg = findcfg(PG_GETARG_OID(0)); + prsobj = findprs(cfg->prs_id); memset(&prs, 0, sizeof(HLPRSTEXT)); prs.lenwords = 32; @@ -557,7 +565,9 @@ headline_byname(PG_FUNCTION_ARGS) { text *cfg = PG_GETARG_TEXT_P(0); - Datum out = DirectFunctionCall4( + Datum out; + SET_FUNCOID(); + out = DirectFunctionCall4( headline, ObjectIdGetDatum(name2id_cfg(cfg)), PG_GETARG_DATUM(1), @@ -574,6 +584,7 @@ Datum headline_current(PG_FUNCTION_ARGS); Datum headline_current(PG_FUNCTION_ARGS) { + SET_FUNCOID(); PG_RETURN_DATUM(DirectFunctionCall4( headline, ObjectIdGetDatum(get_currcfg()),