1 /*-------------------------------------------------------------------------
4 * Standard interface to word parser
6 * Portions Copyright (c) 1996-2008, 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)));