postgresql/contrib/tsearch2/ts_cfg.c

643 lines
14 KiB
C
Raw Normal View History

2003-08-04 02:43:34 +02:00
/*
* interface functions to tscfg
2003-07-21 12:27:44 +02:00
* Teodor Sigaev <teodor@sigaev.ru>
*/
#include "postgres.h"
2003-07-21 12:27:44 +02:00
#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"
2003-07-21 12:27:44 +02:00
#include "ts_cfg.h"
#include "dict.h"
#include "wparser.h"
#include "snmap.h"
#include "common.h"
#include "tsvector.h"
PG_MODULE_MAGIC;
2003-11-25 14:33:15 +01:00
#define IGNORE_LONGLEXEME 1
2003-07-21 12:27:44 +02:00
/*********top interface**********/
2003-08-04 02:43:34 +02:00
static Oid current_cfg_id = 0;
2003-07-21 12:27:44 +02:00
void
2003-08-04 02:43:34 +02:00
init_cfg(Oid id, TSCfgInfo * cfg)
{
Oid arg[2];
2003-08-04 02:43:34 +02:00
bool isnull;
Datum pars[2];
2003-08-04 02:43:34 +02:00
int stat,
i,
j;
text *ptr;
text *prsname = NULL;
2004-08-29 07:07:03 +02:00
char *nsp = get_namespace(TSNSP_FunctionOid);
char buf[1024];
2003-08-04 02:43:34 +02:00
MemoryContext oldcontext;
2004-08-29 07:07:03 +02:00
void *plan;
2003-08-04 02:43:34 +02:00
arg[0] = OIDOID;
arg[1] = OIDOID;
pars[0] = ObjectIdGetDatum(id);
pars[1] = ObjectIdGetDatum(id);
2003-08-04 02:43:34 +02:00
memset(cfg, 0, sizeof(TSCfgInfo));
2003-07-21 12:27:44 +02:00
SPI_connect();
sprintf(buf, "select prs_name from %s.pg_ts_cfg where oid = $1", nsp);
2004-08-29 07:07:03 +02:00
plan = SPI_prepare(buf, 1, arg);
if (!plan)
ts_error(ERROR, "SPI_prepare() failed");
stat = SPI_execp(plan, pars, " ", 1);
2003-08-04 02:43:34 +02:00
if (stat < 0)
ts_error(ERROR, "SPI_execp return %d", stat);
if (SPI_processed > 0)
{
prsname = (text *) DatumGetPointer(
SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull)
);
2003-07-21 12:27:44 +02:00
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
2003-08-04 02:43:34 +02:00
prsname = ptextdup(prsname);
2003-07-21 12:27:44 +02:00
MemoryContextSwitchTo(oldcontext);
2003-08-04 02:43:34 +02:00
cfg->id = id;
}
else
2003-07-21 12:27:44 +02:00
ts_error(ERROR, "No tsearch cfg with id %d", id);
SPI_freeplan(plan);
2003-08-04 02:43:34 +02:00
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);
2004-08-29 07:07:03 +02:00
plan = SPI_prepare(buf, 2, arg);
if (!plan)
ts_error(ERROR, "SPI_prepare() failed");
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
pars[0] = PointerGetDatum(prsname);
stat = SPI_execp(plan, pars, " ", 0);
2003-08-04 02:43:34 +02:00
if (stat < 0)
ts_error(ERROR, "SPI_execp return %d", stat);
if (SPI_processed <= 0)
2003-07-21 12:27:44 +02:00
ts_error(ERROR, "No parser with id %d", id);
2003-08-04 02:43:34 +02:00
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")));
2003-08-04 02:43:34 +02:00
memset(cfg->map, 0, sizeof(ListDictionary) * cfg->len);
2003-07-21 12:27:44 +02:00
}
if (isnull)
continue;
2003-08-04 02:43:34 +02:00
a = (ArrayType *) PointerGetDatum(PG_DETOAST_DATUM(DatumGetPointer(toasted_a)));
if (ARR_NDIM(a) != 1)
ts_error(ERROR, "Wrong dimension");
if (ARRNELEMS(a) < 1)
2003-07-21 12:27:44 +02:00
continue;
if (ARR_HASNULL(a))
ts_error(ERROR, "Array must not contain nulls");
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
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)
2004-08-29 07:07:03 +02:00
ts_error(ERROR, "No memory");
2003-08-04 02:43:34 +02:00
memset(cfg->map[lexid].dict_id, 0, sizeof(Datum) * cfg->map[lexid].len);
ptr = (text *) ARR_DATA_PTR(a);
2003-07-21 12:27:44 +02:00
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
2003-08-04 02:43:34 +02:00
for (j = 0; j < cfg->map[lexid].len; j++)
{
2003-07-21 12:27:44 +02:00
cfg->map[lexid].dict_id[j] = PointerGetDatum(ptextdup(ptr));
2003-08-04 02:43:34 +02:00
ptr = NEXTVAL(ptr);
}
2003-07-21 12:27:44 +02:00
MemoryContextSwitchTo(oldcontext);
2003-08-04 02:43:34 +02:00
if (a != toasted_a)
2003-07-21 12:27:44 +02:00
pfree(a);
}
2003-08-04 02:43:34 +02:00
SPI_freeplan(plan);
2003-07-21 12:27:44 +02:00
SPI_finish();
2003-08-04 02:43:34 +02:00
cfg->prs_id = name2id_prs(prsname);
2003-07-21 12:27:44 +02:00
pfree(prsname);
pfree(nsp);
2003-08-04 02:43:34 +02:00
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));
2003-07-21 12:27:44 +02:00
pfree(ptr);
}
}
}
2003-08-04 02:43:34 +02:00
typedef struct
{
TSCfgInfo *last_cfg;
int len;
int reallen;
TSCfgInfo *list;
2003-07-21 12:27:44 +02:00
SNMap name2id_map;
2003-08-04 02:43:34 +02:00
} CFGList;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
static CFGList CList = {NULL, 0, 0, NULL, {0, 0, NULL}};
2003-07-21 12:27:44 +02:00
void
2003-08-04 02:43:34 +02:00
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)
2003-07-21 12:27:44 +02:00
free(CList.list[i].map[j].dict_id);
2003-08-04 02:43:34 +02:00
free(CList.list[i].map);
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
free(CList.list);
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
memset(&CList, 0, sizeof(CFGList));
2003-07-21 12:27:44 +02:00
}
static int
2003-08-04 02:43:34 +02:00
comparecfg(const void *a, const void *b)
{
2005-10-15 04:49:52 +02:00
if (((TSCfgInfo *) a)->id == ((TSCfgInfo *) b)->id)
return 0;
2005-10-15 04:49:52 +02:00
return (((TSCfgInfo *) a)->id < ((TSCfgInfo *) b)->id) ? -1 : 1;
2003-07-21 12:27:44 +02:00
}
TSCfgInfo *
2003-08-04 02:43:34 +02:00
findcfg(Oid id)
{
2003-07-21 12:27:44 +02:00
/* last used cfg */
2003-08-04 02:43:34 +02:00
if (CList.last_cfg && CList.last_cfg->id == id)
2003-07-21 12:27:44 +02:00
return CList.last_cfg;
/* already used cfg */
2003-08-04 02:43:34 +02:00
if (CList.len != 0)
{
TSCfgInfo key;
key.id = id;
2003-07-21 12:27:44 +02:00
CList.last_cfg = bsearch(&key, CList.list, CList.len, sizeof(TSCfgInfo), comparecfg);
2003-08-04 02:43:34 +02:00
if (CList.last_cfg != NULL)
2003-07-21 12:27:44 +02:00
return CList.last_cfg;
}
/* last chance */
2003-08-04 02:43:34 +02:00
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;
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
CList.last_cfg = &(CList.list[CList.len]);
2003-07-21 12:27:44 +02:00
init_cfg(id, CList.last_cfg);
CList.len++;
qsort(CList.list, CList.len, sizeof(TSCfgInfo), comparecfg);
2003-08-04 02:43:34 +02:00
return findcfg(id); /* qsort changed order!! */ ;
2003-07-21 12:27:44 +02:00
}
Oid
2003-08-04 02:43:34 +02:00
name2id_cfg(text *name)
{
Oid arg[1];
2003-08-04 02:43:34 +02:00
bool isnull;
Datum pars[1];
2003-08-04 02:43:34 +02:00
int stat;
Oid id = findSNMap_t(&(CList.name2id_map), name);
2004-08-29 07:07:03 +02:00
void *plan;
char *nsp;
char buf[1024];
2003-08-04 02:43:34 +02:00
arg[0] = TEXTOID;
pars[0] = PointerGetDatum(name);
2003-08-04 02:43:34 +02:00
if (id)
2003-07-21 12:27:44 +02:00
return id;
2003-08-04 02:43:34 +02:00
2004-08-29 07:07:03 +02:00
nsp = get_namespace(TSNSP_FunctionOid);
2003-07-21 12:27:44 +02:00
SPI_connect();
2004-08-29 07:07:03 +02:00
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");
2003-07-21 12:27:44 +02:00
stat = SPI_execp(plan, pars, " ", 1);
2003-08-04 02:43:34 +02:00
if (stat < 0)
/* internal error */
2003-08-04 02:43:34 +02:00
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")));
2003-08-04 02:43:34 +02:00
}
else
ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("no tsearch config")));
SPI_freeplan(plan);
2003-07-21 12:27:44 +02:00
SPI_finish();
2003-08-04 02:43:34 +02:00
addSNMap_t(&(CList.name2id_map), name, id);
2003-07-21 12:27:44 +02:00
return id;
}
2003-08-04 02:43:34 +02:00
void
parsetext_v2(TSCfgInfo * cfg, PRSTEXT * prs, char *buf, int4 buflen)
{
int type,
lenlemm;
2003-08-04 02:43:34 +02:00
char *lemm = NULL;
2003-07-21 12:27:44 +02:00
WParserInfo *prsobj = findprs(cfg->prs_id);
LexizeData ldata;
TSLexeme *norms;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
prsobj->prs = (void *) DatumGetPointer(
FunctionCall2(
2005-10-15 04:49:52 +02:00
&(prsobj->start_info),
PointerGetDatum(buf),
Int32GetDatum(buflen)
2003-08-04 02:43:34 +02:00
)
);
LexizeInit(&ldata, cfg);
do {
type = DatumGetInt32(FunctionCall3(
2003-08-04 02:43:34 +02:00
&(prsobj->getlexeme_info),
2005-10-15 04:49:52 +02:00
PointerGetDatum(prsobj->prs),
2003-08-04 02:43:34 +02:00
PointerGetDatum(&lemm),
PointerGetDatum(&lenlemm)));
2003-08-04 02:43:34 +02:00
if (type>0 && lenlemm >= MAXSTRLEN)
2004-08-29 07:07:03 +02:00
{
2003-11-25 14:33:15 +01:00
#ifdef IGNORE_LONGLEXEME
ereport(NOTICE,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("A word you are indexing is too long. It will be ignored.")));
2003-11-25 14:33:15 +01:00
continue;
2004-08-29 07:07:03 +02:00
#else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("A word you are indexing is too long")));
2003-11-25 14:33:15 +01:00
#endif
}
2003-07-21 12:27:44 +02:00
LexizeAddLemm(&ldata, type, lemm, lenlemm);
2003-08-04 02:43:34 +02:00
while( (norms = LexizeExec(&ldata, NULL)) != NULL )
2003-08-04 02:43:34 +02:00
{
TSLexeme *ptr = norms;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
prs->pos++; /* set pos */
2003-07-21 12:27:44 +02:00
while (ptr->lexeme)
2003-08-04 02:43:34 +02:00
{
if (prs->curwords == prs->lenwords)
{
2003-07-21 12:27:44 +02:00
prs->lenwords *= 2;
prs->words = (TSWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(TSWORD));
2003-07-21 12:27:44 +02:00
}
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;
2003-07-21 12:27:44 +02:00
prs->words[prs->curwords].alen = 0;
prs->words[prs->curwords].pos.pos = LIMITPOS(prs->pos);
ptr++;
prs->curwords++;
}
pfree(norms);
}
} while(type>0);
2003-07-21 12:27:44 +02:00
FunctionCall1(
2003-08-04 02:43:34 +02:00
&(prsobj->end_info),
PointerGetDatum(prsobj->prs)
);
2003-07-21 12:27:44 +02:00
}
static void
2003-08-04 02:43:34 +02:00
hladdword(HLPRSTEXT * prs, char *buf, int4 buflen, int type)
{
while (prs->curwords >= prs->lenwords)
{
2003-07-21 12:27:44 +02:00
prs->lenwords *= 2;
prs->words = (HLWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(HLWORD));
}
2003-08-04 02:43:34 +02:00
memset(&(prs->words[prs->curwords]), 0, sizeof(HLWORD));
prs->words[prs->curwords].type = (uint8) type;
prs->words[prs->curwords].len = buflen;
2003-07-21 12:27:44 +02:00
prs->words[prs->curwords].word = palloc(buflen);
memcpy(prs->words[prs->curwords].word, buf, buflen);
2003-08-04 02:43:34 +02:00
prs->curwords++;
2003-07-21 12:27:44 +02:00
}
static void
2003-08-04 02:43:34 +02:00
hlfinditem(HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int buflen)
{
int i;
ITEM *item = GETQUERY(query);
HLWORD *word;
2003-08-04 02:43:34 +02:00
while (prs->curwords + query->size >= prs->lenwords)
{
2003-07-21 12:27:44 +02:00
prs->lenwords *= 2;
prs->words = (HLWORD *) repalloc((void *) prs->words, prs->lenwords * sizeof(HLWORD));
}
word = &(prs->words[prs->curwords - 1]);
2003-08-04 02:43:34 +02:00
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;
2003-07-21 12:27:44 +02:00
prs->curwords++;
2003-08-04 02:43:34 +02:00
}
else
word->item = item;
2003-07-21 12:27:44 +02:00
}
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);
}
}
2003-08-04 02:43:34 +02:00
void
hlparsetext(TSCfgInfo * cfg, HLPRSTEXT * prs, QUERYTYPE * query, char *buf, int4 buflen)
{
int type,
lenlemm;
2003-08-04 02:43:34 +02:00
char *lemm = NULL;
2003-07-21 12:27:44 +02:00
WParserInfo *prsobj = findprs(cfg->prs_id);
LexizeData ldata;
TSLexeme *norms;
ParsedLex *lexs;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
prsobj->prs = (void *) DatumGetPointer(
FunctionCall2(
2005-10-15 04:49:52 +02:00
&(prsobj->start_info),
PointerGetDatum(buf),
Int32GetDatum(buflen)
2003-08-04 02:43:34 +02:00
)
);
LexizeInit(&ldata, cfg);
do {
type = DatumGetInt32(FunctionCall3(
2003-08-04 02:43:34 +02:00
&(prsobj->getlexeme_info),
2005-10-15 04:49:52 +02:00
PointerGetDatum(prsobj->prs),
2003-08-04 02:43:34 +02:00
PointerGetDatum(&lemm),
PointerGetDatum(&lenlemm)));
2003-08-04 02:43:34 +02:00
if (type>0 && lenlemm >= MAXSTRLEN)
2004-08-29 07:07:03 +02:00
{
2003-11-25 14:33:15 +01:00
#ifdef IGNORE_LONGLEXEME
ereport(NOTICE,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("A word you are indexing is too long. It will be ignored.")));
2003-11-25 14:33:15 +01:00
continue;
2004-08-29 07:07:03 +02:00
#else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("A word you are indexing is too long")));
2003-11-25 14:33:15 +01:00
#endif
}
2003-07-21 12:27:44 +02:00
LexizeAddLemm(&ldata, type, lemm, lenlemm);
2003-08-04 02:43:34 +02:00
do {
if ( (norms = LexizeExec(&ldata,&lexs)) != NULL )
addHLParsedLex(prs, query, lexs, norms);
else
addHLParsedLex(prs, query, lexs, NULL);
} while( norms );
2003-08-04 02:43:34 +02:00
} while( type>0 );
2003-07-21 12:27:44 +02:00
FunctionCall1(
2003-08-04 02:43:34 +02:00
&(prsobj->end_info),
PointerGetDatum(prsobj->prs)
);
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
text *
genhl(HLPRSTEXT * prs)
{
text *out;
int len = 128;
char *ptr;
HLWORD *wrd = prs->words;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
out = (text *) palloc(len);
ptr = ((char *) out) + VARHDRSZ;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
while (wrd - prs->words < prs->curwords)
{
while (wrd->len + prs->stopsellen + prs->startsellen + (ptr - ((char *) out)) >= len)
{
int dist = ptr - ((char *) out);
len *= 2;
2003-07-21 12:27:44 +02:00
out = (text *) repalloc(out, len);
2003-08-04 02:43:34 +02:00
ptr = ((char *) out) + dist;
2003-07-21 12:27:44 +02:00
}
if (wrd->in && !wrd->repeated)
2003-08-04 02:43:34 +02:00
{
if (wrd->replace)
{
*ptr = ' ';
2003-07-21 12:27:44 +02:00
ptr++;
2003-08-04 02:43:34 +02:00
}
else
{
if (wrd->selected)
{
memcpy(ptr, prs->startsel, prs->startsellen);
ptr += prs->startsellen;
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
memcpy(ptr, wrd->word, wrd->len);
ptr += wrd->len;
if (wrd->selected)
{
memcpy(ptr, prs->stopsel, prs->stopsellen);
ptr += prs->stopsellen;
2003-07-21 12:27:44 +02:00
}
}
2004-08-29 07:07:03 +02:00
}
else if (!wrd->repeated)
2003-07-21 12:27:44 +02:00
pfree(wrd->word);
wrd++;
}
2003-08-04 02:43:34 +02:00
VARATT_SIZEP(out) = ptr - ((char *) out);
return out;
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
int
get_currcfg(void)
{
Oid arg[1] = {TEXTOID};
2003-07-21 12:27:44 +02:00
const char *curlocale;
2003-08-04 02:43:34 +02:00
Datum pars[1];
bool isnull;
int stat;
2004-08-29 07:07:03 +02:00
char buf[1024];
char *nsp;
void *plan;
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
if (current_cfg_id > 0)
2003-07-21 12:27:44 +02:00
return current_cfg_id;
2004-08-29 07:07:03 +02:00
nsp = get_namespace(TSNSP_FunctionOid);
2003-07-21 12:27:44 +02:00
SPI_connect();
2004-08-29 07:07:03 +02:00
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");
2003-07-21 12:27:44 +02:00
curlocale = setlocale(LC_CTYPE, NULL);
2003-08-04 02:43:34 +02:00
pars[0] = PointerGetDatum(char2text((char *) curlocale));
stat = SPI_execp(plan, pars, " ", 1);
2003-07-21 12:27:44 +02:00
2003-08-04 02:43:34 +02:00
if (stat < 0)
/* internal error */
2003-08-04 02:43:34 +02:00
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")));
2003-07-21 12:27:44 +02:00
pfree(DatumGetPointer(pars[0]));
SPI_freeplan(plan);
2003-07-21 12:27:44 +02:00
SPI_finish();
return current_cfg_id;
}
PG_FUNCTION_INFO_V1(set_curcfg);
2003-08-04 02:43:34 +02:00
Datum set_curcfg(PG_FUNCTION_ARGS);
2003-07-21 12:27:44 +02:00
Datum
2003-08-04 02:43:34 +02:00
set_curcfg(PG_FUNCTION_ARGS)
{
2004-08-29 07:07:03 +02:00
SET_FUNCOID();
2003-08-04 02:43:34 +02:00
findcfg(PG_GETARG_OID(0));
current_cfg_id = PG_GETARG_OID(0);
PG_RETURN_VOID();
2003-07-21 12:27:44 +02:00
}
2003-08-04 02:43:34 +02:00
2003-07-21 12:27:44 +02:00
PG_FUNCTION_INFO_V1(set_curcfg_byname);
2003-08-04 02:43:34 +02:00
Datum set_curcfg_byname(PG_FUNCTION_ARGS);
2003-07-21 12:27:44 +02:00
Datum
2003-08-04 02:43:34 +02:00
set_curcfg_byname(PG_FUNCTION_ARGS)
{
text *name = PG_GETARG_TEXT_P(0);
2004-08-29 07:07:03 +02:00
SET_FUNCOID();
2003-08-04 02:43:34 +02:00
DirectFunctionCall1(
set_curcfg,
ObjectIdGetDatum(name2id_cfg(name))
);
PG_FREE_IF_COPY(name, 0);
PG_RETURN_VOID();
}
2003-07-21 12:27:44 +02:00
PG_FUNCTION_INFO_V1(show_curcfg);
2003-08-04 02:43:34 +02:00
Datum show_curcfg(PG_FUNCTION_ARGS);
2003-07-21 12:27:44 +02:00
Datum
2003-08-04 02:43:34 +02:00
show_curcfg(PG_FUNCTION_ARGS)
{
2004-08-29 07:07:03 +02:00
SET_FUNCOID();
2003-08-04 02:43:34 +02:00
PG_RETURN_OID(get_currcfg());
2003-07-21 12:27:44 +02:00
}
PG_FUNCTION_INFO_V1(reset_tsearch);
2003-08-04 02:43:34 +02:00
Datum reset_tsearch(PG_FUNCTION_ARGS);
2003-07-21 12:27:44 +02:00
Datum
2003-08-04 02:43:34 +02:00
reset_tsearch(PG_FUNCTION_ARGS)
{
2004-08-29 07:07:03 +02:00
SET_FUNCOID();
2003-08-04 02:43:34 +02:00
ts_error(NOTICE, "TSearch cache cleaned");
PG_RETURN_VOID();
2003-07-21 12:27:44 +02:00
}