diff options
Diffstat (limited to 'contrib/tsearch2/tsearch2.c')
-rw-r--r-- | contrib/tsearch2/tsearch2.c | 542 |
1 files changed, 0 insertions, 542 deletions
diff --git a/contrib/tsearch2/tsearch2.c b/contrib/tsearch2/tsearch2.c deleted file mode 100644 index 16772a2b92b..00000000000 --- a/contrib/tsearch2/tsearch2.c +++ /dev/null @@ -1,542 +0,0 @@ -/*------------------------------------------------------------------------- - * - * tsearch2.c - * Backwards-compatibility package for old contrib/tsearch2 API - * - * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group - * - * - * IDENTIFICATION - * contrib/tsearch2/tsearch2.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "catalog/namespace.h" -#include "catalog/pg_type.h" -#include "commands/trigger.h" -#include "tsearch/ts_utils.h" -#include "utils/builtins.h" -#include "utils/guc.h" -#include "utils/regproc.h" -#include "utils/syscache.h" - -PG_MODULE_MAGIC; - -static Oid current_dictionary_oid = InvalidOid; -static Oid current_parser_oid = InvalidOid; - -/* insert given value at argument position 0 */ -#define INSERT_ARGUMENT0(argument, isnull) \ - do { \ - int i; \ - for (i = fcinfo->nargs; i > 0; i--) \ - { \ - fcinfo->arg[i] = fcinfo->arg[i-1]; \ - fcinfo->argnull[i] = fcinfo->argnull[i-1]; \ - } \ - fcinfo->arg[0] = (argument); \ - fcinfo->argnull[0] = (isnull); \ - fcinfo->nargs++; \ - } while (0) - -#define TextGetObjectId(infunction, text) \ - DatumGetObjectId(DirectFunctionCall1(infunction, \ - CStringGetDatum(text_to_cstring(text)))) - -#define UNSUPPORTED_FUNCTION(name) \ - PG_FUNCTION_INFO_V1(name); \ - Datum \ - name(PG_FUNCTION_ARGS) \ - { \ - ereport(ERROR, \ - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\ - errmsg("function %s is no longer supported", \ - format_procedure(fcinfo->flinfo->fn_oid)), \ - errhint("Switch to new tsearch functionality."))); \ - /* keep compiler quiet */ \ - PG_RETURN_NULL(); \ - } \ - extern int no_such_variable - -static Oid GetCurrentDict(void); -static Oid GetCurrentParser(void); - -PG_FUNCTION_INFO_V1(tsa_lexize_byname); -PG_FUNCTION_INFO_V1(tsa_lexize_bycurrent); -PG_FUNCTION_INFO_V1(tsa_set_curdict); -PG_FUNCTION_INFO_V1(tsa_set_curdict_byname); -PG_FUNCTION_INFO_V1(tsa_token_type_current); -PG_FUNCTION_INFO_V1(tsa_set_curprs); -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_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); - - -/* - * List of unsupported functions - * - * The parser and dictionary functions are defined only so that the former - * contents of pg_ts_parser and pg_ts_dict can be loaded into the system, - * for ease of reference while creating the new tsearch configuration. - */ - -UNSUPPORTED_FUNCTION(tsa_dex_init); -UNSUPPORTED_FUNCTION(tsa_dex_lexize); - -UNSUPPORTED_FUNCTION(tsa_snb_en_init); -UNSUPPORTED_FUNCTION(tsa_snb_lexize); -UNSUPPORTED_FUNCTION(tsa_snb_ru_init_koi8); -UNSUPPORTED_FUNCTION(tsa_snb_ru_init_utf8); -UNSUPPORTED_FUNCTION(tsa_snb_ru_init); - -UNSUPPORTED_FUNCTION(tsa_spell_init); -UNSUPPORTED_FUNCTION(tsa_spell_lexize); - -UNSUPPORTED_FUNCTION(tsa_syn_init); -UNSUPPORTED_FUNCTION(tsa_syn_lexize); - -UNSUPPORTED_FUNCTION(tsa_thesaurus_init); -UNSUPPORTED_FUNCTION(tsa_thesaurus_lexize); - -UNSUPPORTED_FUNCTION(tsa_prsd_start); -UNSUPPORTED_FUNCTION(tsa_prsd_getlexeme); -UNSUPPORTED_FUNCTION(tsa_prsd_end); -UNSUPPORTED_FUNCTION(tsa_prsd_lextype); -UNSUPPORTED_FUNCTION(tsa_prsd_headline); - -UNSUPPORTED_FUNCTION(tsa_reset_tsearch); -UNSUPPORTED_FUNCTION(tsa_get_covers); - - -/* - * list of redefined functions - */ - -/* lexize(text, text) */ -Datum -tsa_lexize_byname(PG_FUNCTION_ARGS) -{ - text *dictname = PG_GETARG_TEXT_PP(0); - Datum arg1 = PG_GETARG_DATUM(1); - - return DirectFunctionCall2(ts_lexize, - ObjectIdGetDatum(TextGetObjectId(regdictionaryin, dictname)), - arg1); -} - -/* lexize(text) */ -Datum -tsa_lexize_bycurrent(PG_FUNCTION_ARGS) -{ - Datum arg0 = PG_GETARG_DATUM(0); - Oid id = GetCurrentDict(); - - return DirectFunctionCall2(ts_lexize, - ObjectIdGetDatum(id), - arg0); -} - -/* set_curdict(int) */ -Datum -tsa_set_curdict(PG_FUNCTION_ARGS) -{ - Oid dict_oid = PG_GETARG_OID(0); - - if (!SearchSysCacheExists(TSDICTOID, - ObjectIdGetDatum(dict_oid), - 0, 0, 0)) - elog(ERROR, "cache lookup failed for text search dictionary %u", - dict_oid); - - current_dictionary_oid = dict_oid; - - PG_RETURN_VOID(); -} - -/* set_curdict(text) */ -Datum -tsa_set_curdict_byname(PG_FUNCTION_ARGS) -{ - text *name = PG_GETARG_TEXT_PP(0); - Oid dict_oid; - - dict_oid = get_ts_dict_oid(stringToQualifiedNameList(text_to_cstring(name)), false); - - current_dictionary_oid = dict_oid; - - PG_RETURN_VOID(); -} - -/* token_type() */ -Datum -tsa_token_type_current(PG_FUNCTION_ARGS) -{ - INSERT_ARGUMENT0(ObjectIdGetDatum(GetCurrentParser()), false); - return ts_token_type_byid(fcinfo); -} - -/* set_curprs(int) */ -Datum -tsa_set_curprs(PG_FUNCTION_ARGS) -{ - Oid parser_oid = PG_GETARG_OID(0); - - if (!SearchSysCacheExists(TSPARSEROID, - ObjectIdGetDatum(parser_oid), - 0, 0, 0)) - elog(ERROR, "cache lookup failed for text search parser %u", - parser_oid); - - current_parser_oid = parser_oid; - - PG_RETURN_VOID(); -} - -/* set_curprs(text) */ -Datum -tsa_set_curprs_byname(PG_FUNCTION_ARGS) -{ - text *name = PG_GETARG_TEXT_PP(0); - Oid parser_oid; - - parser_oid = get_ts_parser_oid(stringToQualifiedNameList(text_to_cstring(name)), false); - - current_parser_oid = parser_oid; - - PG_RETURN_VOID(); -} - -/* parse(text) */ -Datum -tsa_parse_current(PG_FUNCTION_ARGS) -{ - INSERT_ARGUMENT0(ObjectIdGetDatum(GetCurrentParser()), false); - return ts_parse_byid(fcinfo); -} - -/* set_curcfg(int) */ -Datum -tsa_set_curcfg(PG_FUNCTION_ARGS) -{ - Oid arg0 = PG_GETARG_OID(0); - char *name; - - name = DatumGetCString(DirectFunctionCall1(regconfigout, - ObjectIdGetDatum(arg0))); - - SetConfigOption("default_text_search_config", name, - PGC_USERSET, PGC_S_SESSION); - - PG_RETURN_VOID(); -} - -/* set_curcfg(text) */ -Datum -tsa_set_curcfg_byname(PG_FUNCTION_ARGS) -{ - text *arg0 = PG_GETARG_TEXT_PP(0); - char *name; - - name = text_to_cstring(arg0); - - SetConfigOption("default_text_search_config", name, - PGC_USERSET, PGC_S_SESSION); - - PG_RETURN_VOID(); -} - -/* to_tsvector(text, text) */ -Datum -tsa_to_tsvector_name(PG_FUNCTION_ARGS) -{ - text *cfgname = PG_GETARG_TEXT_PP(0); - Datum arg1 = PG_GETARG_DATUM(1); - Oid config_oid; - - config_oid = TextGetObjectId(regconfigin, cfgname); - - return DirectFunctionCall2(to_tsvector_byid, - ObjectIdGetDatum(config_oid), arg1); -} - -/* to_tsquery(text, text) */ -Datum -tsa_to_tsquery_name(PG_FUNCTION_ARGS) -{ - text *cfgname = PG_GETARG_TEXT_PP(0); - Datum arg1 = PG_GETARG_DATUM(1); - Oid config_oid; - - config_oid = TextGetObjectId(regconfigin, cfgname); - - return DirectFunctionCall2(to_tsquery_byid, - ObjectIdGetDatum(config_oid), arg1); -} - - -/* plainto_tsquery(text, text) */ -Datum -tsa_plainto_tsquery_name(PG_FUNCTION_ARGS) -{ - text *cfgname = PG_GETARG_TEXT_PP(0); - Datum arg1 = PG_GETARG_DATUM(1); - Oid config_oid; - - config_oid = TextGetObjectId(regconfigin, cfgname); - - return DirectFunctionCall2(plainto_tsquery_byid, - ObjectIdGetDatum(config_oid), arg1); -} - -/* headline(text, text, tsquery [,text]) */ -Datum -tsa_headline_byname(PG_FUNCTION_ARGS) -{ - Datum arg0 = PG_GETARG_DATUM(0); - Datum arg1 = PG_GETARG_DATUM(1); - Datum arg2 = PG_GETARG_DATUM(2); - Datum result; - Oid config_oid; - - /* first parameter has to be converted to oid */ - config_oid = DatumGetObjectId(DirectFunctionCall1(regconfigin, - CStringGetDatum(TextDatumGetCString(arg0)))); - - if (PG_NARGS() == 3) - result = DirectFunctionCall3(ts_headline_byid, - ObjectIdGetDatum(config_oid), arg1, arg2); - else - { - Datum arg3 = PG_GETARG_DATUM(3); - - result = DirectFunctionCall4(ts_headline_byid_opt, - ObjectIdGetDatum(config_oid), - arg1, arg2, arg3); - } - - return result; -} - -/* - * tsearch2 version of update trigger - * - * We pass this on to the core trigger after inserting the default text - * search configuration name as the second argument. Note that this isn't - * a complete implementation of the original functionality; tsearch2 allowed - * transformation function names to be included in the list. However, that - * is deliberately removed as being a security risk. - */ -Datum -tsa_tsearch2(PG_FUNCTION_ARGS) -{ - TriggerData *trigdata; - Trigger *trigger; - char **tgargs, - **tgargs_old; - int i; - Datum res; - - /* Check call context */ - if (!CALLED_AS_TRIGGER(fcinfo)) /* internal error */ - elog(ERROR, "tsvector_update_trigger: not fired by trigger manager"); - - trigdata = (TriggerData *) fcinfo->context; - trigger = trigdata->tg_trigger; - - if (trigger->tgnargs < 2) - elog(ERROR, "TSearch: format tsearch2(tsvector_field, text_field1,...)"); - - /* create space for configuration name */ - tgargs = (char **) palloc((trigger->tgnargs + 1) * sizeof(char *)); - tgargs[0] = trigger->tgargs[0]; - for (i = 1; i < trigger->tgnargs; i++) - tgargs[i + 1] = trigger->tgargs[i]; - - tgargs[1] = pstrdup(GetConfigOptionByName("default_text_search_config", - NULL, false)); - tgargs_old = trigger->tgargs; - trigger->tgargs = tgargs; - trigger->tgnargs++; - - res = tsvector_update_trigger_byid(fcinfo); - - /* restore old trigger data */ - trigger->tgargs = tgargs_old; - trigger->tgnargs--; - - pfree(tgargs[1]); - pfree(tgargs); - - return res; -} - - -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; - - if (!AggCheckCallContext(fcinfo, &aggcontext)) - elog(ERROR, "tsa_rewrite_accum called in non-aggregate context"); - - 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 - */ -static Oid -GetCurrentDict(void) -{ - if (current_dictionary_oid == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("no current dictionary"), - errhint("Execute SELECT set_curdict(...)."))); - - return current_dictionary_oid; -} - -/* - * Get Oid of current parser - * - * Here, it seems reasonable to select the "default" parser if none has been - * set. - */ -static Oid -GetCurrentParser(void) -{ - if (current_parser_oid == InvalidOid) - current_parser_oid = get_ts_parser_oid(stringToQualifiedNameList("pg_catalog.default"), false); - return current_parser_oid; -} |