1
/*-------------------------------------------------------------------------
4
* Standard interface to word parser
6
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
12
*-------------------------------------------------------------------------
17
#include "access/genam.h"
18
#include "access/skey.h"
19
#include "catalog/indexing.h"
20
#include "catalog/namespace.h"
21
#include "catalog/pg_ts_parser.h"
22
#include "catalog/pg_type.h"
23
#include "commands/defrem.h"
24
#include "tsearch/ts_cache.h"
25
#include "tsearch/ts_public.h"
26
#include "tsearch/ts_utils.h"
27
#include "utils/builtins.h"
28
#include "utils/fmgroids.h"
29
#include "utils/rel.h"
30
#include "utils/syscache.h"
33
/******sql-level interface******/
42
tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
45
MemoryContext oldcontext;
46
TSTokenTypeStorage *st;
47
TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
49
if (!OidIsValid(prs->lextypeOid))
50
elog(ERROR, "method lextype isn't defined for text search parser %u",
53
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
55
st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
57
/* OidFunctionCall0 is absent */
58
st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
60
funcctx->user_fctx = (void *) st;
62
tupdesc = CreateTemplateTupleDesc(3, false);
63
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
65
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "alias",
67
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
70
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
71
MemoryContextSwitchTo(oldcontext);
75
tt_process_call(FuncCallContext *funcctx)
77
TSTokenTypeStorage *st;
79
st = (TSTokenTypeStorage *) funcctx->user_fctx;
80
if (st->list && st->list[st->cur].lexid)
87
sprintf(txtid, "%d", st->list[st->cur].lexid);
89
values[1] = st->list[st->cur].alias;
90
values[2] = st->list[st->cur].descr;
92
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
93
result = HeapTupleGetDatum(tuple);
107
ts_token_type_byid(PG_FUNCTION_ARGS)
109
FuncCallContext *funcctx;
112
if (SRF_IS_FIRSTCALL())
114
funcctx = SRF_FIRSTCALL_INIT();
115
tt_setup_firstcall(funcctx, PG_GETARG_OID(0));
118
funcctx = SRF_PERCALL_SETUP();
120
if ((result = tt_process_call(funcctx)) != (Datum) 0)
121
SRF_RETURN_NEXT(funcctx, result);
122
SRF_RETURN_DONE(funcctx);
126
ts_token_type_byname(PG_FUNCTION_ARGS)
128
FuncCallContext *funcctx;
131
if (SRF_IS_FIRSTCALL())
133
text *prsname = PG_GETARG_TEXT_P(0);
136
funcctx = SRF_FIRSTCALL_INIT();
137
prsId = TSParserGetPrsid(textToQualifiedNameList(prsname), false);
138
tt_setup_firstcall(funcctx, prsId);
141
funcctx = SRF_PERCALL_SETUP();
143
if ((result = tt_process_call(funcctx)) != (Datum) 0)
144
SRF_RETURN_NEXT(funcctx, result);
145
SRF_RETURN_DONE(funcctx);
163
prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt)
166
MemoryContext oldcontext;
168
TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
174
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
176
st = (PrsStorage *) palloc(sizeof(PrsStorage));
179
st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
181
prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart,
182
PointerGetDatum(VARDATA(txt)),
183
Int32GetDatum(VARSIZE(txt) - VARHDRSZ)));
185
while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
186
PointerGetDatum(prsdata),
187
PointerGetDatum(&lex),
188
PointerGetDatum(&llen)))) != 0)
190
if (st->cur >= st->len)
192
st->len = 2 * st->len;
193
st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
195
st->list[st->cur].lexeme = palloc(llen + 1);
196
memcpy(st->list[st->cur].lexeme, lex, llen);
197
st->list[st->cur].lexeme[llen] = '\0';
198
st->list[st->cur].type = type;
202
FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
207
funcctx->user_fctx = (void *) st;
208
tupdesc = CreateTemplateTupleDesc(2, false);
209
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
211
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token",
214
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
215
MemoryContextSwitchTo(oldcontext);
219
prs_process_call(FuncCallContext *funcctx)
223
st = (PrsStorage *) funcctx->user_fctx;
224
if (st->cur < st->len)
232
sprintf(tid, "%d", st->list[st->cur].type);
233
values[1] = st->list[st->cur].lexeme;
234
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
235
result = HeapTupleGetDatum(tuple);
251
ts_parse_byid(PG_FUNCTION_ARGS)
253
FuncCallContext *funcctx;
256
if (SRF_IS_FIRSTCALL())
258
text *txt = PG_GETARG_TEXT_P(1);
260
funcctx = SRF_FIRSTCALL_INIT();
261
prs_setup_firstcall(funcctx, PG_GETARG_OID(0), txt);
262
PG_FREE_IF_COPY(txt, 1);
265
funcctx = SRF_PERCALL_SETUP();
267
if ((result = prs_process_call(funcctx)) != (Datum) 0)
268
SRF_RETURN_NEXT(funcctx, result);
269
SRF_RETURN_DONE(funcctx);
273
ts_parse_byname(PG_FUNCTION_ARGS)
275
FuncCallContext *funcctx;
278
if (SRF_IS_FIRSTCALL())
280
text *prsname = PG_GETARG_TEXT_P(0);
281
text *txt = PG_GETARG_TEXT_P(1);
284
funcctx = SRF_FIRSTCALL_INIT();
285
prsId = TSParserGetPrsid(textToQualifiedNameList(prsname), false);
286
prs_setup_firstcall(funcctx, prsId, txt);
289
funcctx = SRF_PERCALL_SETUP();
291
if ((result = prs_process_call(funcctx)) != (Datum) 0)
292
SRF_RETURN_NEXT(funcctx, result);
293
SRF_RETURN_DONE(funcctx);
297
ts_headline_byid_opt(PG_FUNCTION_ARGS)
299
text *in = PG_GETARG_TEXT_P(1);
300
TSQuery query = PG_GETARG_TSQUERY(2);
301
text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
302
HeadlineParsedText prs;
305
TSConfigCacheEntry *cfg;
306
TSParserCacheEntry *prsobj;
308
cfg = lookup_ts_config_cache(PG_GETARG_OID(0));
309
prsobj = lookup_ts_parser_cache(cfg->prsId);
311
if (!OidIsValid(prsobj->headlineOid))
313
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
314
errmsg("text search parser does not support headline creation")));
316
memset(&prs, 0, sizeof(HeadlineParsedText));
318
prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
320
hlparsetext(cfg->cfgId, &prs, query, VARDATA(in), VARSIZE(in) - VARHDRSZ);
323
prsoptions = deserialize_deflist(PointerGetDatum(opt));
327
FunctionCall3(&(prsobj->prsheadline),
328
PointerGetDatum(&prs),
329
PointerGetDatum(prsoptions),
330
PointerGetDatum(query));
332
out = generateHeadline(&prs);
334
PG_FREE_IF_COPY(in, 1);
335
PG_FREE_IF_COPY(query, 2);
337
PG_FREE_IF_COPY(opt, 3);
342
PG_RETURN_POINTER(out);
346
ts_headline_byid(PG_FUNCTION_ARGS)
348
PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
351
PG_GETARG_DATUM(2)));
355
ts_headline(PG_FUNCTION_ARGS)
357
PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
358
ObjectIdGetDatum(getTSCurrentConfig(true)),
360
PG_GETARG_DATUM(1)));
364
ts_headline_opt(PG_FUNCTION_ARGS)
366
PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_byid_opt,
367
ObjectIdGetDatum(getTSCurrentConfig(true)),
370
PG_GETARG_DATUM(2)));