Force a checkpoint in CREATE DATABASE before starting to copy the files,
[PostgreSQL.git] / src / backend / tsearch / wparser.c
blob829dcc3fb5dba9f275145f83ca6d7d768fe40be9
1 /*-------------------------------------------------------------------------
3 * wparser.c
4 * Standard interface to word parser
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
9 * IDENTIFICATION
10 * $PostgreSQL$
12 *-------------------------------------------------------------------------
14 #include "postgres.h"
16 #include "funcapi.h"
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******/
35 typedef struct
37 int cur;
38 LexDescr *list;
39 } TSTokenTypeStorage;
41 static void
42 tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
44 TupleDesc tupdesc;
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",
51 prsid);
53 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
55 st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
56 st->cur = 0;
57 /* OidFunctionCall0 is absent */
58 st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
59 (Datum) 0));
60 funcctx->user_fctx = (void *) st;
62 tupdesc = CreateTemplateTupleDesc(3, false);
63 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
64 INT4OID, -1, 0);
65 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "alias",
66 TEXTOID, -1, 0);
67 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description",
68 TEXTOID, -1, 0);
70 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
71 MemoryContextSwitchTo(oldcontext);
74 static Datum
75 tt_process_call(FuncCallContext *funcctx)
77 TSTokenTypeStorage *st;
79 st = (TSTokenTypeStorage *) funcctx->user_fctx;
80 if (st->list && st->list[st->cur].lexid)
82 Datum result;
83 char *values[3];
84 char txtid[16];
85 HeapTuple tuple;
87 sprintf(txtid, "%d", st->list[st->cur].lexid);
88 values[0] = txtid;
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);
95 pfree(values[1]);
96 pfree(values[2]);
97 st->cur++;
98 return result;
100 if (st->list)
101 pfree(st->list);
102 pfree(st);
103 return (Datum) 0;
106 Datum
107 ts_token_type_byid(PG_FUNCTION_ARGS)
109 FuncCallContext *funcctx;
110 Datum result;
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);
125 Datum
126 ts_token_type_byname(PG_FUNCTION_ARGS)
128 FuncCallContext *funcctx;
129 Datum result;
131 if (SRF_IS_FIRSTCALL())
133 text *prsname = PG_GETARG_TEXT_P(0);
134 Oid prsId;
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);
148 typedef struct
150 int type;
151 char *lexeme;
152 } LexemeEntry;
154 typedef struct
156 int cur;
157 int len;
158 LexemeEntry *list;
159 } PrsStorage;
162 static void
163 prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt)
165 TupleDesc tupdesc;
166 MemoryContext oldcontext;
167 PrsStorage *st;
168 TSParserCacheEntry *prs = lookup_ts_parser_cache(prsid);
169 char *lex = NULL;
170 int llen = 0,
171 type = 0;
172 void *prsdata;
174 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
176 st = (PrsStorage *) palloc(sizeof(PrsStorage));
177 st->cur = 0;
178 st->len = 16;
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;
199 st->cur++;
202 FunctionCall1(&prs->prsend, PointerGetDatum(prsdata));
204 st->len = st->cur;
205 st->cur = 0;
207 funcctx->user_fctx = (void *) st;
208 tupdesc = CreateTemplateTupleDesc(2, false);
209 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
210 INT4OID, -1, 0);
211 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token",
212 TEXTOID, -1, 0);
214 funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
215 MemoryContextSwitchTo(oldcontext);
218 static Datum
219 prs_process_call(FuncCallContext *funcctx)
221 PrsStorage *st;
223 st = (PrsStorage *) funcctx->user_fctx;
224 if (st->cur < st->len)
226 Datum result;
227 char *values[2];
228 char tid[16];
229 HeapTuple tuple;
231 values[0] = tid;
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);
237 pfree(values[1]);
238 st->cur++;
239 return result;
241 else
243 if (st->list)
244 pfree(st->list);
245 pfree(st);
247 return (Datum) 0;
250 Datum
251 ts_parse_byid(PG_FUNCTION_ARGS)
253 FuncCallContext *funcctx;
254 Datum result;
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);
272 Datum
273 ts_parse_byname(PG_FUNCTION_ARGS)
275 FuncCallContext *funcctx;
276 Datum result;
278 if (SRF_IS_FIRSTCALL())
280 text *prsname = PG_GETARG_TEXT_P(0);
281 text *txt = PG_GETARG_TEXT_P(1);
282 Oid prsId;
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);
296 Datum
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;
303 List *prsoptions;
304 text *out;
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))
312 ereport(ERROR,
313 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
314 errmsg("text search parser does not support headline creation")));
316 memset(&prs, 0, sizeof(HeadlineParsedText));
317 prs.lenwords = 32;
318 prs.words = (HeadlineWordEntry *) palloc(sizeof(HeadlineWordEntry) * prs.lenwords);
320 hlparsetext(cfg->cfgId, &prs, query, VARDATA(in), VARSIZE(in) - VARHDRSZ);
322 if (opt)
323 prsoptions = deserialize_deflist(PointerGetDatum(opt));
324 else
325 prsoptions = NIL;
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);
336 if (opt)
337 PG_FREE_IF_COPY(opt, 3);
338 pfree(prs.words);
339 pfree(prs.startsel);
340 pfree(prs.stopsel);
342 PG_RETURN_POINTER(out);
345 Datum
346 ts_headline_byid(PG_FUNCTION_ARGS)
348 PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
349 PG_GETARG_DATUM(0),
350 PG_GETARG_DATUM(1),
351 PG_GETARG_DATUM(2)));
354 Datum
355 ts_headline(PG_FUNCTION_ARGS)
357 PG_RETURN_DATUM(DirectFunctionCall3(ts_headline_byid_opt,
358 ObjectIdGetDatum(getTSCurrentConfig(true)),
359 PG_GETARG_DATUM(0),
360 PG_GETARG_DATUM(1)));
363 Datum
364 ts_headline_opt(PG_FUNCTION_ARGS)
366 PG_RETURN_DATUM(DirectFunctionCall4(ts_headline_byid_opt,
367 ObjectIdGetDatum(getTSCurrentConfig(true)),
368 PG_GETARG_DATUM(0),
369 PG_GETARG_DATUM(1),
370 PG_GETARG_DATUM(2)));