1 /*-------------------------------------------------------------------------
4 * Standard interface to word parser
6 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
10 * src/backend/tsearch/wparser.c
12 *-------------------------------------------------------------------------
17 #include "catalog/namespace.h"
18 #include "catalog/pg_type.h"
19 #include "commands/defrem.h"
20 #include "tsearch/ts_cache.h"
21 #include "tsearch/ts_utils.h"
22 #include "utils/builtins.h"
25 /******sql-level interface******/
34 tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
37 MemoryContext oldcontext;
38 TSTokenTypeStorage *st;
39 TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
41 if (!OidIsValid(prs->lextypeOid))
42 elog(ERROR, "method lextype isn't defined for text search parser %u",
45 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
47 st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
49 /* lextype takes one dummy argument */
50 st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
52 funcctx->user_fctx = (void *) st;
54 tupdesc = CreateTemplateTupleDesc(3, false);
55 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
57 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "alias",
59 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
62 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
63 MemoryContextSwitchTo(oldcontext);
67 tt_process_call(FuncCallContext *funcctx)
69 TSTokenTypeStorage *st;
71 st = (TSTokenTypeStorage *) funcctx->user_fctx;
72 if (st->list && st->list[st->cur].lexid)
79 sprintf(txtid, "%d", st->list[st->cur].lexid);
81 values[1] = st->list[st->cur].alias;
82 values[2] = st->list[st->cur].descr;
84 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
85 result = HeapTupleGetDatum(tuple);
99 ts_token_type_byid(PG_FUNCTION_ARGS)
101 FuncCallContext *funcctx;
104 if (SRF_IS_FIRSTCALL())
106 funcctx = SRF_FIRSTCALL_INIT();
107 tt_setup_firstcall(funcctx, PG_GETARG_OID(0));
110 funcctx = SRF_PERCALL_SETUP();
112 if ((result = tt_process_call(funcctx)) != (Datum) 0)
113 SRF_RETURN_NEXT(funcctx, result);
114 SRF_RETURN_DONE(funcctx);
118 ts_token_type_byname(PG_FUNCTION_ARGS)
120 FuncCallContext *funcctx;
123 if (SRF_IS_FIRSTCALL())
125 text *prsname = PG_GETARG_TEXT_P(0);
128 funcctx = SRF_FIRSTCALL_INIT();
129 prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
130 tt_setup_firstcall(funcctx, prsId);
133 funcctx = SRF_PERCALL_SETUP();
135 if ((result = tt_process_call(funcctx)) != (Datum) 0)
136 SRF_RETURN_NEXT(funcctx, result);
137 SRF_RETURN_DONE(funcctx);
155 prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt)
158 MemoryContext oldcontext;
160 TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
166 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
168 st = (PrsStorage *) palloc(sizeof(PrsStorage));
171 st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
173 prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart,
174 PointerGetDatum(VARDATA(txt)),
175 Int32GetDatum(VARSIZE(txt) - VARHDRSZ)));
177 while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
178 PointerGetDatum(prsdata),
179 PointerGetDatum(&lex),
180 PointerGetDatum(&llen)))) != 0)
182 if (st->cur >= st->len)
184 st->len = 2 * st->len;
185 st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
187 st->list[st->cur].lexeme = palloc(llen + 1);
188 memcpy(st->list[st->cur].lexeme, lex, llen);
189 st->list[st->cur].lexeme[llen] = '\0';
190 st->list[st->cur].type = type;
194 FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
199 funcctx->user_fctx = (void *) st;
200 tupdesc = CreateTemplateTupleDesc(2, false);
201 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
203 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token",
206 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
207 MemoryContextSwitchTo(oldcontext);
211 prs_process_call(FuncCallContext *funcctx)
215 st = (PrsStorage *) funcctx->user_fctx;
216 if (st->cur < st->len)
224 sprintf(tid, "%d", st->list[st->cur].type);
225 values[1] = st->list[st->cur].lexeme;
226 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
227 result = HeapTupleGetDatum(tuple);
243 ts_parse_byid(PG_FUNCTION_ARGS)
245 FuncCallContext *funcctx;
248 if (SRF_IS_FIRSTCALL())
250 text *txt = PG_GETARG_TEXT_P(1);
252 funcctx = SRF_FIRSTCALL_INIT();
253 prs_setup_firstcall(funcctx, PG_GETARG_OID(0), txt);
254 PG_FREE_IF_COPY(txt, 1);
257 funcctx = SRF_PERCALL_SETUP();
259 if ((result = prs_process_call(funcctx)) != (Datum) 0)
260 SRF_RETURN_NEXT(funcctx, result);
261 SRF_RETURN_DONE(funcctx);
265 ts_parse_byname(PG_FUNCTION_ARGS)
267 FuncCallContext *funcctx;
270 if (SRF_IS_FIRSTCALL())
272 text *prsname = PG_GETARG_TEXT_P(0);
273 text *txt = PG_GETARG_TEXT_P(1);
276 funcctx = SRF_FIRSTCALL_INIT();
277 prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false);
278 prs_setup_firstcall(funcctx, prsId, txt);
281 funcctx = SRF_PERCALL_SETUP();
283 if ((result = prs_process_call(funcctx)) != (Datum) 0)
284 SRF_RETURN_NEXT(funcctx, result);
285 SRF_RETURN_DONE(funcctx);
289 ts_headline_byid_opt(PG_FUNCTION_ARGS)
291 text *in = PG_GETARG_TEXT_P(1);
292 TSQuery query = PG_GETARG_TSQUERY(2);
293 text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
294 HeadlineParsedText prs;
297 TSConfigCacheEntry *cfg;
298 TSParserCacheEntry *prsobj;
300 cfg = lookup_ts_config_cache(PG_GETARG_OID(0));
301 prsobj = lookup_ts_parser_cache(cfg->prsId);
303 if (!OidIsValid(prsobj->headlineOid))
305 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
306 errmsg("text search parser does not support headline creation")));
308 memset(&prs, 0, sizeof(HeadlineParsedText));
310 prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
312 hlparsetext(cfg->cfgId, &prs, query, VARDATA(in), VARSIZE(in) - VARHDRSZ);
315 prsoptions = deserialize_deflist(PointerGetDatum(opt));
319 FunctionCall3(&(prsobj->prsheadline),
320 PointerGetDatum(&prs),
321 PointerGetDatum(prsoptions),
322 PointerGetDatum(query));
324 out = generateHeadline(&prs);
326 PG_FREE_IF_COPY(in, 1);
327 PG_FREE_IF_COPY(query, 2);
329 PG_FREE_IF_COPY(opt, 3);
334 PG_RETURN_POINTER(out);
338 ts_headline_byid(PG_FUNCTION_ARGS)
340 PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
343 PG_GETARG_DATUM(2)));
347 ts_headline(PG_FUNCTION_ARGS)
349 PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
350 ObjectIdGetDatum(getTSCurrentConfig(true)),
352 PG_GETARG_DATUM(1)));
356 ts_headline_opt(PG_FUNCTION_ARGS)
358 PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_byid_opt,
359 ObjectIdGetDatum(getTSCurrentConfig(true)),
362 PG_GETARG_DATUM(2)));