diff options
Diffstat (limited to 'contrib/tsearch2/ts_cfg.c')
-rw-r--r-- | contrib/tsearch2/ts_cfg.c | 648 |
1 files changed, 0 insertions, 648 deletions
diff --git a/contrib/tsearch2/ts_cfg.c b/contrib/tsearch2/ts_cfg.c deleted file mode 100644 index 646ffc1481..0000000000 --- a/contrib/tsearch2/ts_cfg.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * interface functions to tscfg - * Teodor Sigaev <[email protected]> - */ -#include "postgres.h" - -#include <ctype.h> -#include <locale.h> - -#include "catalog/pg_type.h" -#include "executor/spi.h" -#include "fmgr.h" -#include "utils/array.h" -#include "utils/memutils.h" - -#include "ts_cfg.h" -#include "dict.h" -#include "wparser.h" -#include "snmap.h" -#include "common.h" -#include "tsvector.h" - -PG_MODULE_MAGIC; - -#define IGNORE_LONGLEXEME 1 - -/*********top interface**********/ - -static Oid current_cfg_id = 0; - -void -init_cfg(Oid id, TSCfgInfo * cfg) -{ - Oid arg[2]; - bool isnull; - Datum pars[2]; - int stat, - i, - 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; - pars[0] = ObjectIdGetDatum(id); - pars[1] = ObjectIdGetDatum(id); - - memset(cfg, 0, sizeof(TSCfgInfo)); - SPI_connect(); - - 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) - { - prsname = DatumGetTextP(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - prsname = ptextdup(prsname); - MemoryContextSwitchTo(oldcontext); - - cfg->id = id; - } - else - ts_error(ERROR, "No tsearch cfg with id %d", id); - - SPI_freeplan(plan); - - arg[0] = TEXTOID; - 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, pars, " ", 0); - if (stat < 0) - ts_error(ERROR, "SPI_execp return %d", stat); - if (SPI_processed <= 0) - ts_error(ERROR, "No parser with id %d", id); - - for (i = 0; i < SPI_processed; i++) - { - int lexid = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull)); - ArrayType *toasted_a = (ArrayType *) PointerGetDatum(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnull)); - ArrayType *a; - - if (!cfg->map) - { - cfg->len = lexid + 1; - cfg->map = (ListDictionary *) malloc(sizeof(ListDictionary) * cfg->len); - if (!cfg->map) - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - memset(cfg->map, 0, sizeof(ListDictionary) * cfg->len); - } - - if (isnull) - continue; - - a = (ArrayType *) PointerGetDatum(PG_DETOAST_DATUM(DatumGetPointer(toasted_a))); - - if (ARR_NDIM(a) != 1) - ts_error(ERROR, "Wrong dimension"); - if (ARRNELEMS(a) < 1) - continue; - if (ARR_HASNULL(a)) - ts_error(ERROR, "Array must not contain nulls"); - - cfg->map[lexid].len = ARRNELEMS(a); - cfg->map[lexid].dict_id = (Datum *) malloc(sizeof(Datum) * cfg->map[lexid].len); - if (!cfg->map[lexid].dict_id) - ts_error(ERROR, "No memory"); - - memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len); - ptr = (text *) ARR_DATA_PTR(a); - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - for (j = 0; j < cfg->map[lexid].len; j++) - { - cfg->map[lexid].dict_id[j] = PointerGetDatum(ptextdup(ptr)); - ptr = NEXTVAL(ptr); - } - MemoryContextSwitchTo(oldcontext); - - if (a != toasted_a) - 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++) - { - ptr = (text *) DatumGetPointer(cfg->map[i].dict_id[j]); - cfg->map[i].dict_id[j] = ObjectIdGetDatum(name2id_dict(ptr)); - pfree(ptr); - } - } -} - -typedef struct -{ - TSCfgInfo *last_cfg; - int len; - int reallen; - TSCfgInfo *list; - SNMap name2id_map; -} CFGList; - -static CFGList CList = {NULL, 0, 0, NULL, {0, 0, NULL}}; - -void -reset_cfg(void) -{ - freeSNMap(&(CList.name2id_map)); - if (CList.list) - { - int i, - j; - - for (i = 0; i < CList.len; i++) - if (CList.list[i].map) - { - for (j = 0; j < CList.list[i].len; j++) - if (CList.list[i].map[j].dict_id) - free(CList.list[i].map[j].dict_id); - free(CList.list[i].map); - } - free(CList.list); - } - memset(&CList, 0, sizeof(CFGList)); -} - -static int -comparecfg(const void *a, const void *b) -{ - if (((TSCfgInfo *) a)->id == ((TSCfgInfo *) b)->id) - return 0; - return (((TSCfgInfo *) a)->id < ((TSCfgInfo *) b)->id) ? -1 : 1; -} - -TSCfgInfo * -findcfg(Oid id) -{ - /* last used cfg */ - if (CList.last_cfg && CList.last_cfg->id == id) - return CList.last_cfg; - - /* already used cfg */ - if (CList.len != 0) - { - TSCfgInfo key; - - key.id = id; - CList.last_cfg = bsearch(&key, CList.list, CList.len, sizeof(TSCfgInfo), comparecfg); - if (CList.last_cfg != NULL) - return CList.last_cfg; - } - - /* last chance */ - if (CList.len == CList.reallen) - { - TSCfgInfo *tmp; - int reallen = (CList.reallen) ? 2 * CList.reallen : 16; - - tmp = (TSCfgInfo *) realloc(CList.list, sizeof(TSCfgInfo) * reallen); - if (!tmp) - ts_error(ERROR, "No memory"); - CList.reallen = reallen; - CList.list = tmp; - } - init_cfg(id, &(CList.list[CList.len]) ); - CList.last_cfg = &(CList.list[CList.len]); - CList.len++; - qsort(CList.list, CList.len, sizeof(TSCfgInfo), comparecfg); - return findcfg(id); /* qsort changed order!! */ ; -} - - -Oid -name2id_cfg(text *name) -{ - Oid arg[1]; - bool isnull; - 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); - - if (id) - return id; - - nsp = get_namespace(TSNSP_FunctionOid); - SPI_connect(); - 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, pars, " ", 1); - if (stat < 0) - /* internal error */ - elog(ERROR, "SPI_execp return %d", stat); - if (SPI_processed > 0) - { - id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); - if (isnull) - ereport(ERROR, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("null id for tsearch config"))); - } - else - ereport(ERROR, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("no tsearch config"))); - - SPI_freeplan(plan); - SPI_finish(); - addSNMap_t(&(CList.name2id_map), name, id); - return id; -} - -void -parsetext_v2(TSCfgInfo * cfg, PRSTEXT * prs, char *buf, int4 buflen) -{ - int type, - lenlemm; - char *lemm = NULL; - WParserInfo *prsobj = findprs(cfg->prs_id); - LexizeData ldata; - TSLexeme *norms; - - prsobj->prs = (void *) DatumGetPointer( - FunctionCall2( - &(prsobj->start_info), - PointerGetDatum(buf), - Int32GetDatum(buflen) - ) - ); - - LexizeInit(&ldata, cfg); - - do - { - type = DatumGetInt32(FunctionCall3( - &(prsobj->getlexeme_info), - PointerGetDatum(prsobj->prs), - PointerGetDatum(&lemm), - PointerGetDatum(&lenlemm))); - - if (type > 0 && lenlemm >= MAXSTRLEN) - { -#ifdef IGNORE_LONGLEXEME - ereport(NOTICE, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("A word you are indexing is too long. It will be ignored."))); - continue; -#else - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("A word you are indexing is too long"))); -#endif - } - - LexizeAddLemm(&ldata, type, lemm, lenlemm); - - while ((norms = LexizeExec(&ldata, NULL)) != NULL) - { - TSLexeme *ptr = norms; - - prs->pos++; /* set pos */ - - while (ptr->lexeme) - { - if (prs->curwords == prs->lenwords) - { - prs->lenwords *= 2; - prs->words = (TSWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(TSWORD)); - } - - if (ptr->flags & TSL_ADDPOS) - prs->pos++; - prs->words[prs->curwords].len = strlen(ptr->lexeme); - prs->words[prs->curwords].word = ptr->lexeme; - prs->words[prs->curwords].nvariant = ptr->nvariant; - prs->words[prs->curwords].alen = 0; - prs->words[prs->curwords].pos.pos = LIMITPOS(prs->pos); - ptr++; - prs->curwords++; - } - pfree(norms); - } - } while (type > 0); - - FunctionCall1( - &(prsobj->end_info), - PointerGetDatum(prsobj->prs) - ); -} - -static void -hladdword(HLPRSTEXT * prs, char *buf, int4 buflen, int type) -{ - while (prs->curwords >= prs->lenwords) - { - prs->lenwords *= 2; - prs->words = (HLWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(HLWORD)); - } - memset(&(prs->words[prs->curwords]), 0, sizeof(HLWORD)); - prs->words[prs->curwords].type = (uint8) type; - prs->words[prs->curwords].len = buflen; - prs->words[prs->curwords].word = palloc(buflen); - memcpy(prs->words[prs->curwords].word, buf, buflen); - prs->curwords++; -} - -static void -hlfinditem(HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int buflen) -{ - int i; - ITEM *item = GETQUERY(query); - HLWORD *word; - - while (prs->curwords + query->size >= prs->lenwords) - { - prs->lenwords *= 2; - prs->words = (HLWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(HLWORD)); - } - - word = &(prs->words[prs->curwords - 1]); - for (i = 0; i < query->size; i++) - { - if (item->type == VAL && item->length == buflen && strncmp(GETOPERAND(query) + item->distance, buf, buflen) == 0) - { - if (word->item) - { - memcpy(&(prs->words[prs->curwords]), word, sizeof(HLWORD)); - prs->words[prs->curwords].item = item; - prs->words[prs->curwords].repeated = 1; - prs->curwords++; - } - else - word->item = item; - } - item++; - } -} - -static void -addHLParsedLex(HLPRSTEXT * prs, QUERYTYPE * query, ParsedLex * lexs, TSLexeme * norms) -{ - ParsedLex *tmplexs; - TSLexeme *ptr; - - while (lexs) - { - - if (lexs->type > 0) - hladdword(prs, lexs->lemm, lexs->lenlemm, lexs->type); - - ptr = norms; - while (ptr && ptr->lexeme) - { - hlfinditem(prs, query, ptr->lexeme, strlen(ptr->lexeme)); - ptr++; - } - - tmplexs = lexs->next; - pfree(lexs); - lexs = tmplexs; - } - - if (norms) - { - ptr = norms; - while (ptr->lexeme) - { - pfree(ptr->lexeme); - ptr++; - } - pfree(norms); - } -} - -void -hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4 buflen) -{ - int type, - lenlemm; - char *lemm = NULL; - WParserInfo *prsobj = findprs(cfg->prs_id); - LexizeData ldata; - TSLexeme *norms; - ParsedLex *lexs; - - prsobj->prs = (void *) DatumGetPointer( - FunctionCall2( - &(prsobj->start_info), - PointerGetDatum(buf), - Int32GetDatum(buflen) - ) - ); - - LexizeInit(&ldata, cfg); - - do - { - type = DatumGetInt32(FunctionCall3( - &(prsobj->getlexeme_info), - PointerGetDatum(prsobj->prs), - PointerGetDatum(&lemm), - PointerGetDatum(&lenlemm))); - - if (type > 0 && lenlemm >= MAXSTRLEN) - { -#ifdef IGNORE_LONGLEXEME - ereport(NOTICE, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("A word you are indexing is too long. It will be ignored."))); - continue; -#else - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("A word you are indexing is too long"))); -#endif - } - - LexizeAddLemm(&ldata, type, lemm, lenlemm); - - do - { - if ((norms = LexizeExec(&ldata, &lexs)) != NULL) - addHLParsedLex(prs, query, lexs, norms); - else - addHLParsedLex(prs, query, lexs, NULL); - } while (norms); - - } while (type > 0); - - FunctionCall1( - &(prsobj->end_info), - PointerGetDatum(prsobj->prs) - ); -} - -text * -genhl(HLPRSTEXT * prs) -{ - text *out; - int len = 128; - char *ptr; - HLWORD *wrd = prs->words; - - out = (text *) palloc(len); - ptr = ((char *) out) + VARHDRSZ; - - while (wrd - prs->words < prs->curwords) - { - while (wrd->len + prs->stopsellen + prs->startsellen + (ptr - ((char *) out)) >= len) - { - int dist = ptr - ((char *) out); - - len *= 2; - out = (text *) repalloc(out, len); - ptr = ((char *) out) + dist; - } - - if (wrd->in && !wrd->repeated) - { - if (wrd->replace) - { - *ptr = ' '; - ptr++; - } - else - { - if (wrd->selected) - { - memcpy(ptr, prs->startsel, prs->startsellen); - ptr += prs->startsellen; - } - memcpy(ptr, wrd->word, wrd->len); - ptr += wrd->len; - if (wrd->selected) - { - memcpy(ptr, prs->stopsel, prs->stopsellen); - ptr += prs->stopsellen; - } - } - } - else if (!wrd->repeated) - pfree(wrd->word); - - wrd++; - } - - SET_VARSIZE(out, ptr - ((char *) out)); - return out; -} - -int -get_currcfg(void) -{ - Oid arg[1] = {TEXTOID}; - const char *curlocale; - 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(); - 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, pars, " ", 1); - - if (stat < 0) - /* internal error */ - elog(ERROR, "SPI_execp return %d", stat); - if (SPI_processed > 0) - current_cfg_id = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)); - else - ereport(ERROR, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("could not find tsearch config by locale"))); - - pfree(DatumGetPointer(pars[0])); - SPI_freeplan(plan); - SPI_finish(); - return current_cfg_id; -} - -PG_FUNCTION_INFO_V1(set_curcfg); -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(); -} - -PG_FUNCTION_INFO_V1(set_curcfg_byname); -Datum set_curcfg_byname(PG_FUNCTION_ARGS); -Datum -set_curcfg_byname(PG_FUNCTION_ARGS) -{ - text *name = PG_GETARG_TEXT_P(0); - - SET_FUNCOID(); - DirectFunctionCall1( - set_curcfg, - ObjectIdGetDatum(name2id_cfg(name)) - ); - PG_FREE_IF_COPY(name, 0); - PG_RETURN_VOID(); -} - -PG_FUNCTION_INFO_V1(show_curcfg); -Datum show_curcfg(PG_FUNCTION_ARGS); -Datum -show_curcfg(PG_FUNCTION_ARGS) -{ - SET_FUNCOID(); - PG_RETURN_OID(get_currcfg()); -} - -PG_FUNCTION_INFO_V1(reset_tsearch); -Datum reset_tsearch(PG_FUNCTION_ARGS); -Datum -reset_tsearch(PG_FUNCTION_ARGS) -{ - SET_FUNCOID(); - ts_error(NOTICE, "TSearch cache cleaned"); - PG_RETURN_VOID(); -} |