1 /*-------------------------------------------------------------------------
4 * Standard interface to word parser
6 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
10 * $PostgreSQL: pgsql/src/backend/tsearch/wparser.c,v 1.12 2010/01/02 16:57:53 momjian Exp $
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)));