1 /*-------------------------------------------------------------------------
4 * Standard interface to word parser
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
10 * $PostgreSQL: pgsql/src/backend/tsearch/wparser.c,v 1.8 2008/01/15 18:22:47 tgl Exp $
12 *-------------------------------------------------------------------------
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "access/skey.h"
20 #include "catalog/indexing.h"
21 #include "catalog/namespace.h"
22 #include "catalog/pg_ts_parser.h"
23 #include "catalog/pg_type.h"
24 #include "commands/defrem.h"
25 #include "tsearch/ts_cache.h"
26 #include "tsearch/ts_public.h"
27 #include "tsearch/ts_utils.h"
28 #include "utils/builtins.h"
29 #include "utils/fmgroids.h"
30 #include "utils/rel.h"
31 #include "utils/syscache.h"
34 /******sql-level interface******/
43 tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
46 MemoryContext oldcontext;
47 TSTokenTypeStorage *st;
48 TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
50 if (!OidIsValid(prs->lextypeOid))
51 elog(ERROR, "method lextype isn't defined for text search parser %u",
54 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
56 st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
58 /* OidFunctionCall0 is absent */
59 st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
61 funcctx->user_fctx = (void *) st;
63 tupdesc = CreateTemplateTupleDesc(3, false);
64 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
66 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "alias",
68 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
71 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
72 MemoryContextSwitchTo(oldcontext);
76 tt_process_call(FuncCallContext *funcctx)
78 TSTokenTypeStorage *st;
80 st = (TSTokenTypeStorage *) funcctx->user_fctx;
81 if (st->list && st->list[st->cur].lexid)
88 sprintf(txtid, "%d", st->list[st->cur].lexid);
90 values[1] = st->list[st->cur].alias;
91 values[2] = st->list[st->cur].descr;
93 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
94 result = HeapTupleGetDatum(tuple);
108 ts_token_type_byid(PG_FUNCTION_ARGS)
110 FuncCallContext *funcctx;
113 if (SRF_IS_FIRSTCALL())
115 funcctx = SRF_FIRSTCALL_INIT();
116 tt_setup_firstcall(funcctx, PG_GETARG_OID(0));
119 funcctx = SRF_PERCALL_SETUP();
121 if ((result = tt_process_call(funcctx)) != (Datum) 0)
122 SRF_RETURN_NEXT(funcctx, result);
123 SRF_RETURN_DONE(funcctx);
127 ts_token_type_byname(PG_FUNCTION_ARGS)
129 FuncCallContext *funcctx;
132 if (SRF_IS_FIRSTCALL())
134 text *prsname = PG_GETARG_TEXT_P(0);
137 funcctx = SRF_FIRSTCALL_INIT();
138 prsId = TSParserGetPrsid(textToQualifiedNameList(prsname), false);
139 tt_setup_firstcall(funcctx, prsId);
142 funcctx = SRF_PERCALL_SETUP();
144 if ((result = tt_process_call(funcctx)) != (Datum) 0)
145 SRF_RETURN_NEXT(funcctx, result);
146 SRF_RETURN_DONE(funcctx);
164 prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt)
167 MemoryContext oldcontext;
169 TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
175 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
177 st = (PrsStorage *) palloc(sizeof(PrsStorage));
180 st->list = (LexemeEntry *) palloc(sizeof(LexemeEntry) * st->len);
182 prsdata = (void *) DatumGetPointer(FunctionCall2(&prs->prsstart,
183 PointerGetDatum(VARDATA(txt)),
184 Int32GetDatum(VARSIZE(txt) - VARHDRSZ)));
186 while ((type = DatumGetInt32(FunctionCall3(&prs->prstoken,
187 PointerGetDatum(prsdata),
188 PointerGetDatum(&lex),
189 PointerGetDatum(&llen)))) != 0)
191 if (st->cur >= st->len)
193 st->len = 2 * st->len;
194 st->list = (LexemeEntry *) repalloc(st->list, sizeof(LexemeEntry) * st->len);
196 st->list[st->cur].lexeme = palloc(llen + 1);
197 memcpy(st->list[st->cur].lexeme, lex, llen);
198 st->list[st->cur].lexeme[llen] = '\0';
199 st->list[st->cur].type = type;
203 FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
208 funcctx->user_fctx = (void *) st;
209 tupdesc = CreateTemplateTupleDesc(2, false);
210 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
212 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token",
215 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
216 MemoryContextSwitchTo(oldcontext);
220 prs_process_call(FuncCallContext *funcctx)
224 st = (PrsStorage *) funcctx->user_fctx;
225 if (st->cur < st->len)
233 sprintf(tid, "%d", st->list[st->cur].type);
234 values[1] = st->list[st->cur].lexeme;
235 tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
236 result = HeapTupleGetDatum(tuple);
252 ts_parse_byid(PG_FUNCTION_ARGS)
254 FuncCallContext *funcctx;
257 if (SRF_IS_FIRSTCALL())
259 text *txt = PG_GETARG_TEXT_P(1);
261 funcctx = SRF_FIRSTCALL_INIT();
262 prs_setup_firstcall(funcctx, PG_GETARG_OID(0), txt);
263 PG_FREE_IF_COPY(txt, 1);
266 funcctx = SRF_PERCALL_SETUP();
268 if ((result = prs_process_call(funcctx)) != (Datum) 0)
269 SRF_RETURN_NEXT(funcctx, result);
270 SRF_RETURN_DONE(funcctx);
274 ts_parse_byname(PG_FUNCTION_ARGS)
276 FuncCallContext *funcctx;
279 if (SRF_IS_FIRSTCALL())
281 text *prsname = PG_GETARG_TEXT_P(0);
282 text *txt = PG_GETARG_TEXT_P(1);
285 funcctx = SRF_FIRSTCALL_INIT();
286 prsId = TSParserGetPrsid(textToQualifiedNameList(prsname), false);
287 prs_setup_firstcall(funcctx, prsId, txt);
290 funcctx = SRF_PERCALL_SETUP();
292 if ((result = prs_process_call(funcctx)) != (Datum) 0)
293 SRF_RETURN_NEXT(funcctx, result);
294 SRF_RETURN_DONE(funcctx);
298 ts_headline_byid_opt(PG_FUNCTION_ARGS)
300 text *in = PG_GETARG_TEXT_P(1);
301 TSQuery query = PG_GETARG_TSQUERY(2);
302 text *opt = (PG_NARGS() > 3 && PG_GETARG_POINTER(3)) ? PG_GETARG_TEXT_P(3) : NULL;
303 HeadlineParsedText prs;
306 TSConfigCacheEntry *cfg;
307 TSParserCacheEntry *prsobj;
309 cfg = lookup_ts_config_cache(PG_GETARG_OID(0));
310 prsobj = lookup_ts_parser_cache(cfg->prsId);
312 if (!OidIsValid(prsobj->headlineOid))
314 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
315 errmsg("text search parser does not support headline creation")));
317 memset(&prs, 0, sizeof(HeadlineParsedText));
319 prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
321 hlparsetext(cfg->cfgId, &prs, query, VARDATA(in), VARSIZE(in) - VARHDRSZ);
324 prsoptions = deserialize_deflist(PointerGetDatum(opt));
328 FunctionCall3(&(prsobj->prsheadline),
329 PointerGetDatum(&prs),
330 PointerGetDatum(prsoptions),
331 PointerGetDatum(query));
333 out = generateHeadline(&prs);
335 PG_FREE_IF_COPY(in, 1);
336 PG_FREE_IF_COPY(query, 2);
338 PG_FREE_IF_COPY(opt, 3);
343 PG_RETURN_POINTER(out);
347 ts_headline_byid(PG_FUNCTION_ARGS)
349 PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
352 PG_GETARG_DATUM(2)));
356 ts_headline(PG_FUNCTION_ARGS)
358 PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
359 ObjectIdGetDatum(getTSCurrentConfig(true)),
361 PG_GETARG_DATUM(1)));
365 ts_headline_opt(PG_FUNCTION_ARGS)
367 PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_byid_opt,
368 ObjectIdGetDatum(getTSCurrentConfig(true)),
371 PG_GETARG_DATUM(2)));