PostgreSQL Source Code git master
ts_cache.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * ts_cache.c
4 * Tsearch related object caches.
5 *
6 * Tsearch performance is very sensitive to performance of parsers,
7 * dictionaries and mapping, so lookups should be cached as much
8 * as possible.
9 *
10 * Once a backend has created a cache entry for a particular TS object OID,
11 * the cache entry will exist for the life of the backend; hence it is
12 * safe to hold onto a pointer to the cache entry while doing things that
13 * might result in recognizing a cache invalidation. Beware however that
14 * subsidiary information might be deleted and reallocated somewhere else
15 * if a cache inval and reval happens! This does not look like it will be
16 * a big problem as long as parser and dictionary methods do not attempt
17 * any database access.
18 *
19 *
20 * Copyright (c) 2006-2025, PostgreSQL Global Development Group
21 *
22 * IDENTIFICATION
23 * src/backend/utils/cache/ts_cache.c
24 *
25 *-------------------------------------------------------------------------
26 */
27#include "postgres.h"
28
29#include "access/genam.h"
30#include "access/htup_details.h"
31#include "access/table.h"
32#include "access/xact.h"
33#include "catalog/namespace.h"
36#include "catalog/pg_ts_dict.h"
39#include "commands/defrem.h"
40#include "miscadmin.h"
41#include "nodes/miscnodes.h"
42#include "tsearch/ts_cache.h"
43#include "utils/builtins.h"
44#include "utils/catcache.h"
45#include "utils/fmgroids.h"
46#include "utils/guc_hooks.h"
47#include "utils/inval.h"
48#include "utils/lsyscache.h"
49#include "utils/memutils.h"
50#include "utils/regproc.h"
51#include "utils/syscache.h"
52
53
54/*
55 * MAXTOKENTYPE/MAXDICTSPERTT are arbitrary limits on the workspace size
56 * used in lookup_ts_config_cache(). We could avoid hardwiring a limit
57 * by making the workspace dynamically enlargeable, but it seems unlikely
58 * to be worth the trouble.
59 */
60#define MAXTOKENTYPE 256
61#define MAXDICTSPERTT 100
62
63
64static HTAB *TSParserCacheHash = NULL;
66
69
70static HTAB *TSConfigCacheHash = NULL;
72
73/*
74 * GUC default_text_search_config, and a cache of the current config's OID
75 */
76char *TSCurrentConfig = NULL;
77
79
80
81/*
82 * We use this syscache callback to detect when a visible change to a TS
83 * catalog entry has been made, by either our own backend or another one.
84 *
85 * In principle we could just flush the specific cache entry that changed,
86 * but given that TS configuration changes are probably infrequent, it
87 * doesn't seem worth the trouble to determine that; we just flush all the
88 * entries of the related hash table.
89 *
90 * We can use the same function for all TS caches by passing the hash
91 * table address as the "arg".
92 */
93static void
94InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
95{
97 HASH_SEQ_STATUS status;
98 TSAnyCacheEntry *entry;
99
100 hash_seq_init(&status, hash);
101 while ((entry = (TSAnyCacheEntry *) hash_seq_search(&status)) != NULL)
102 entry->isvalid = false;
103
104 /* Also invalidate the current-config cache if it's pg_ts_config */
105 if (hash == TSConfigCacheHash)
107}
108
109/*
110 * Fetch parser cache entry
111 */
114{
115 TSParserCacheEntry *entry;
116
117 if (TSParserCacheHash == NULL)
118 {
119 /* First time through: initialize the hash table */
120 HASHCTL ctl;
121
122 ctl.keysize = sizeof(Oid);
123 ctl.entrysize = sizeof(TSParserCacheEntry);
124 TSParserCacheHash = hash_create("Tsearch parser cache", 4,
126 /* Flush cache on pg_ts_parser changes */
129
130 /* Also make sure CacheMemoryContext exists */
133 }
134
135 /* Check single-entry cache */
136 if (lastUsedParser && lastUsedParser->prsId == prsId &&
138 return lastUsedParser;
139
140 /* Try to look up an existing entry */
142 &prsId,
143 HASH_FIND, NULL);
144 if (entry == NULL || !entry->isvalid)
145 {
146 /*
147 * If we didn't find one, we want to make one. But first look up the
148 * object to be sure the OID is real.
149 */
150 HeapTuple tp;
152
153 tp = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
154 if (!HeapTupleIsValid(tp))
155 elog(ERROR, "cache lookup failed for text search parser %u",
156 prsId);
157 prs = (Form_pg_ts_parser) GETSTRUCT(tp);
158
159 /*
160 * Sanity checks
161 */
162 if (!OidIsValid(prs->prsstart))
163 elog(ERROR, "text search parser %u has no prsstart method", prsId);
164 if (!OidIsValid(prs->prstoken))
165 elog(ERROR, "text search parser %u has no prstoken method", prsId);
166 if (!OidIsValid(prs->prsend))
167 elog(ERROR, "text search parser %u has no prsend method", prsId);
168
169 if (entry == NULL)
170 {
171 bool found;
172
173 /* Now make the cache entry */
174 entry = (TSParserCacheEntry *)
175 hash_search(TSParserCacheHash, &prsId, HASH_ENTER, &found);
176 Assert(!found); /* it wasn't there a moment ago */
177 }
178
179 MemSet(entry, 0, sizeof(TSParserCacheEntry));
180 entry->prsId = prsId;
181 entry->startOid = prs->prsstart;
182 entry->tokenOid = prs->prstoken;
183 entry->endOid = prs->prsend;
184 entry->headlineOid = prs->prsheadline;
185 entry->lextypeOid = prs->prslextype;
186
187 ReleaseSysCache(tp);
188
192 if (OidIsValid(entry->headlineOid))
193 fmgr_info_cxt(entry->headlineOid, &entry->prsheadline,
195
196 entry->isvalid = true;
197 }
198
199 lastUsedParser = entry;
200
201 return entry;
202}
203
204/*
205 * Fetch dictionary cache entry
206 */
209{
211
212 if (TSDictionaryCacheHash == NULL)
213 {
214 /* First time through: initialize the hash table */
215 HASHCTL ctl;
216
217 ctl.keysize = sizeof(Oid);
218 ctl.entrysize = sizeof(TSDictionaryCacheEntry);
219 TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
221 /* Flush cache on pg_ts_dict and pg_ts_template changes */
226
227 /* Also make sure CacheMemoryContext exists */
230 }
231
232 /* Check single-entry cache */
233 if (lastUsedDictionary && lastUsedDictionary->dictId == dictId &&
235 return lastUsedDictionary;
236
237 /* Try to look up an existing entry */
239 &dictId,
240 HASH_FIND, NULL);
241 if (entry == NULL || !entry->isvalid)
242 {
243 /*
244 * If we didn't find one, we want to make one. But first look up the
245 * object to be sure the OID is real.
246 */
247 HeapTuple tpdict,
248 tptmpl;
249 Form_pg_ts_dict dict;
250 Form_pg_ts_template template;
251 MemoryContext saveCtx;
252
253 tpdict = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
254 if (!HeapTupleIsValid(tpdict))
255 elog(ERROR, "cache lookup failed for text search dictionary %u",
256 dictId);
257 dict = (Form_pg_ts_dict) GETSTRUCT(tpdict);
258
259 /*
260 * Sanity checks
261 */
262 if (!OidIsValid(dict->dicttemplate))
263 elog(ERROR, "text search dictionary %u has no template", dictId);
264
265 /*
266 * Retrieve dictionary's template
267 */
268 tptmpl = SearchSysCache1(TSTEMPLATEOID,
269 ObjectIdGetDatum(dict->dicttemplate));
270 if (!HeapTupleIsValid(tptmpl))
271 elog(ERROR, "cache lookup failed for text search template %u",
272 dict->dicttemplate);
273 template = (Form_pg_ts_template) GETSTRUCT(tptmpl);
274
275 /*
276 * Sanity checks
277 */
278 if (!OidIsValid(template->tmpllexize))
279 elog(ERROR, "text search template %u has no lexize method",
280 template->tmpllexize);
281
282 if (entry == NULL)
283 {
284 bool found;
285
286 /* Now make the cache entry */
287 entry = (TSDictionaryCacheEntry *)
289 &dictId,
290 HASH_ENTER, &found);
291 Assert(!found); /* it wasn't there a moment ago */
292
293 /* Create private memory context the first time through */
295 "TS dictionary",
297 MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
298 }
299 else
300 {
301 /* Clear the existing entry's private context */
302 saveCtx = entry->dictCtx;
303 /* Don't let context's ident pointer dangle while we reset it */
304 MemoryContextSetIdentifier(saveCtx, NULL);
305 MemoryContextReset(saveCtx);
306 MemoryContextCopyAndSetIdentifier(saveCtx, NameStr(dict->dictname));
307 }
308
309 MemSet(entry, 0, sizeof(TSDictionaryCacheEntry));
310 entry->dictId = dictId;
311 entry->dictCtx = saveCtx;
312
313 entry->lexizeOid = template->tmpllexize;
314
315 if (OidIsValid(template->tmplinit))
316 {
317 List *dictoptions;
318 Datum opt;
319 bool isnull;
320 MemoryContext oldcontext;
321
322 /*
323 * Init method runs in dictionary's private memory context, and we
324 * make sure the options are stored there too
325 */
326 oldcontext = MemoryContextSwitchTo(entry->dictCtx);
327
328 opt = SysCacheGetAttr(TSDICTOID, tpdict,
329 Anum_pg_ts_dict_dictinitoption,
330 &isnull);
331 if (isnull)
332 dictoptions = NIL;
333 else
334 dictoptions = deserialize_deflist(opt);
335
336 entry->dictData =
337 DatumGetPointer(OidFunctionCall1(template->tmplinit,
338 PointerGetDatum(dictoptions)));
339
340 MemoryContextSwitchTo(oldcontext);
341 }
342
343 ReleaseSysCache(tptmpl);
344 ReleaseSysCache(tpdict);
345
346 fmgr_info_cxt(entry->lexizeOid, &entry->lexize, entry->dictCtx);
347
348 entry->isvalid = true;
349 }
350
351 lastUsedDictionary = entry;
352
353 return entry;
354}
355
356/*
357 * Initialize config cache and prepare callbacks. This is split out of
358 * lookup_ts_config_cache because we need to activate the callback before
359 * caching TSCurrentConfigCache, too.
360 */
361static void
363{
364 HASHCTL ctl;
365
366 ctl.keysize = sizeof(Oid);
367 ctl.entrysize = sizeof(TSConfigCacheEntry);
368 TSConfigCacheHash = hash_create("Tsearch configuration cache", 16,
370 /* Flush cache on pg_ts_config and pg_ts_config_map changes */
375
376 /* Also make sure CacheMemoryContext exists */
379}
380
381/*
382 * Fetch configuration cache entry
383 */
386{
387 TSConfigCacheEntry *entry;
388
389 if (TSConfigCacheHash == NULL)
390 {
391 /* First time through: initialize the hash table */
393 }
394
395 /* Check single-entry cache */
396 if (lastUsedConfig && lastUsedConfig->cfgId == cfgId &&
398 return lastUsedConfig;
399
400 /* Try to look up an existing entry */
402 &cfgId,
403 HASH_FIND, NULL);
404 if (entry == NULL || !entry->isvalid)
405 {
406 /*
407 * If we didn't find one, we want to make one. But first look up the
408 * object to be sure the OID is real.
409 */
410 HeapTuple tp;
412 Relation maprel;
413 Relation mapidx;
414 ScanKeyData mapskey;
415 SysScanDesc mapscan;
416 HeapTuple maptup;
417 ListDictionary maplists[MAXTOKENTYPE + 1];
418 Oid mapdicts[MAXDICTSPERTT];
419 int maxtokentype;
420 int ndicts;
421 int i;
422
423 tp = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
424 if (!HeapTupleIsValid(tp))
425 elog(ERROR, "cache lookup failed for text search configuration %u",
426 cfgId);
427 cfg = (Form_pg_ts_config) GETSTRUCT(tp);
428
429 /*
430 * Sanity checks
431 */
432 if (!OidIsValid(cfg->cfgparser))
433 elog(ERROR, "text search configuration %u has no parser", cfgId);
434
435 if (entry == NULL)
436 {
437 bool found;
438
439 /* Now make the cache entry */
440 entry = (TSConfigCacheEntry *)
442 &cfgId,
443 HASH_ENTER, &found);
444 Assert(!found); /* it wasn't there a moment ago */
445 }
446 else
447 {
448 /* Cleanup old contents */
449 if (entry->map)
450 {
451 for (i = 0; i < entry->lenmap; i++)
452 if (entry->map[i].dictIds)
453 pfree(entry->map[i].dictIds);
454 pfree(entry->map);
455 }
456 }
457
458 MemSet(entry, 0, sizeof(TSConfigCacheEntry));
459 entry->cfgId = cfgId;
460 entry->prsId = cfg->cfgparser;
461
462 ReleaseSysCache(tp);
463
464 /*
465 * Scan pg_ts_config_map to gather dictionary list for each token type
466 *
467 * Because the index is on (mapcfg, maptokentype, mapseqno), we will
468 * see the entries in maptokentype order, and in mapseqno order for
469 * each token type, even though we didn't explicitly ask for that.
470 */
471 MemSet(maplists, 0, sizeof(maplists));
472 maxtokentype = 0;
473 ndicts = 0;
474
475 ScanKeyInit(&mapskey,
476 Anum_pg_ts_config_map_mapcfg,
477 BTEqualStrategyNumber, F_OIDEQ,
478 ObjectIdGetDatum(cfgId));
479
480 maprel = table_open(TSConfigMapRelationId, AccessShareLock);
481 mapidx = index_open(TSConfigMapIndexId, AccessShareLock);
482 mapscan = systable_beginscan_ordered(maprel, mapidx,
483 NULL, 1, &mapskey);
484
485 while ((maptup = systable_getnext_ordered(mapscan, ForwardScanDirection)) != NULL)
486 {
488 int toktype = cfgmap->maptokentype;
489
490 if (toktype <= 0 || toktype > MAXTOKENTYPE)
491 elog(ERROR, "maptokentype value %d is out of range", toktype);
492 if (toktype < maxtokentype)
493 elog(ERROR, "maptokentype entries are out of order");
494 if (toktype > maxtokentype)
495 {
496 /* starting a new token type, but first save the prior data */
497 if (ndicts > 0)
498 {
499 maplists[maxtokentype].len = ndicts;
500 maplists[maxtokentype].dictIds = (Oid *)
502 sizeof(Oid) * ndicts);
503 memcpy(maplists[maxtokentype].dictIds, mapdicts,
504 sizeof(Oid) * ndicts);
505 }
506 maxtokentype = toktype;
507 mapdicts[0] = cfgmap->mapdict;
508 ndicts = 1;
509 }
510 else
511 {
512 /* continuing data for current token type */
513 if (ndicts >= MAXDICTSPERTT)
514 elog(ERROR, "too many pg_ts_config_map entries for one token type");
515 mapdicts[ndicts++] = cfgmap->mapdict;
516 }
517 }
518
522
523 if (ndicts > 0)
524 {
525 /* save the last token type's dictionaries */
526 maplists[maxtokentype].len = ndicts;
527 maplists[maxtokentype].dictIds = (Oid *)
529 sizeof(Oid) * ndicts);
530 memcpy(maplists[maxtokentype].dictIds, mapdicts,
531 sizeof(Oid) * ndicts);
532 /* and save the overall map */
533 entry->lenmap = maxtokentype + 1;
534 entry->map = (ListDictionary *)
536 sizeof(ListDictionary) * entry->lenmap);
537 memcpy(entry->map, maplists,
538 sizeof(ListDictionary) * entry->lenmap);
539 }
540
541 entry->isvalid = true;
542 }
543
544 lastUsedConfig = entry;
545
546 return entry;
547}
548
549
550/*---------------------------------------------------
551 * GUC variable "default_text_search_config"
552 *---------------------------------------------------
553 */
554
555Oid
556getTSCurrentConfig(bool emitError)
557{
558 List *namelist;
559
560 /* if we have a cached value, return it */
563
564 /* fail if GUC hasn't been set up yet */
565 if (TSCurrentConfig == NULL || *TSCurrentConfig == '\0')
566 {
567 if (emitError)
568 elog(ERROR, "text search configuration isn't set");
569 else
570 return InvalidOid;
571 }
572
573 if (TSConfigCacheHash == NULL)
574 {
575 /* First time through: initialize the tsconfig inval callback */
577 }
578
579 /* Look up the config */
580 if (emitError)
581 {
583 TSCurrentConfigCache = get_ts_config_oid(namelist, false);
584 }
585 else
586 {
587 ErrorSaveContext escontext = {T_ErrorSaveContext};
588
590 (Node *) &escontext);
591 if (namelist != NIL)
592 TSCurrentConfigCache = get_ts_config_oid(namelist, true);
593 else
594 TSCurrentConfigCache = InvalidOid; /* bad name list syntax */
595 }
596
598}
599
600/* GUC check_hook for default_text_search_config */
601bool
603{
604 /*
605 * If we aren't inside a transaction, or connected to a database, we
606 * cannot do the catalog accesses necessary to verify the config name.
607 * Must accept it on faith.
608 */
610 {
611 ErrorSaveContext escontext = {T_ErrorSaveContext};
612 List *namelist;
613 Oid cfgId;
614 HeapTuple tuple;
616 char *buf;
617
619 (Node *) &escontext);
620 if (namelist != NIL)
621 cfgId = get_ts_config_oid(namelist, true);
622 else
623 cfgId = InvalidOid; /* bad name list syntax */
624
625 /*
626 * When source == PGC_S_TEST, don't throw a hard error for a
627 * nonexistent configuration, only a NOTICE. See comments in guc.h.
628 */
629 if (!OidIsValid(cfgId))
630 {
631 if (source == PGC_S_TEST)
632 {
634 (errcode(ERRCODE_UNDEFINED_OBJECT),
635 errmsg("text search configuration \"%s\" does not exist", *newval)));
636 return true;
637 }
638 else
639 return false;
640 }
641
642 /*
643 * Modify the actually stored value to be fully qualified, to ensure
644 * later changes of search_path don't affect it.
645 */
646 tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
647 if (!HeapTupleIsValid(tuple))
648 elog(ERROR, "cache lookup failed for text search configuration %u",
649 cfgId);
650 cfg = (Form_pg_ts_config) GETSTRUCT(tuple);
651
653 NameStr(cfg->cfgname));
654
655 ReleaseSysCache(tuple);
656
657 /* GUC wants it guc_malloc'd not palloc'd */
660 pfree(buf);
661 if (!*newval)
662 return false;
663 }
664
665 return true;
666}
667
668/* GUC assign_hook for default_text_search_config */
669void
671{
672 /* Just reset the cache to force a lookup on first use */
674}
#define NameStr(name)
Definition: c.h:717
uint32_t uint32
Definition: c.h:502
#define MemSet(start, val, len)
Definition: c.h:991
#define OidIsValid(objectId)
Definition: c.h:746
void CreateCacheMemoryContext(void)
Definition: catcache.c:708
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1420
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:679
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:650
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:757
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:732
Oid MyDatabaseId
Definition: globals.c:93
void guc_free(void *ptr)
Definition: guc.c:689
#define newval
char * guc_strdup(int elevel, const char *src)
Definition: guc.c:677
GucSource
Definition: guc.h:112
@ PGC_S_TEST
Definition: guc.h:125
Assert(PointerIsAligned(start, uint64))
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1802
int i
Definition: isn.c:74
#define AccessShareLock
Definition: lockdefs.h:36
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3449
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void pfree(void *pointer)
Definition: mcxt.c:1524
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:612
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:101
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:3152
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
void * arg
#define NIL
Definition: pg_list.h:68
static rewind_source * source
Definition: pg_rewind.c:89
static char * buf
Definition: pg_test_fsync.c:72
FormData_pg_ts_config * Form_pg_ts_config
Definition: pg_ts_config.h:48
FormData_pg_ts_config_map * Form_pg_ts_config_map
FormData_pg_ts_dict * Form_pg_ts_dict
Definition: pg_ts_dict.h:52
FormData_pg_ts_parser * Form_pg_ts_parser
Definition: pg_ts_parser.h:55
FormData_pg_ts_template * Form_pg_ts_template
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
tree ctl
Definition: radixtree.h:1838
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
List * stringToQualifiedNameList(const char *string, Node *escontext)
Definition: regproc.c:1797
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:13103
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
@ ForwardScanDirection
Definition: sdir.h:28
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Definition: dynahash.c:220
Oid * dictIds
Definition: ts_cache.h:68
Definition: pg_list.h:54
Definition: nodes.h:131
ListDictionary * map
Definition: ts_cache.h:80
MemoryContext dictCtx
Definition: ts_cache.h:61
FmgrInfo prstoken
Definition: ts_cache.h:46
FmgrInfo prsstart
Definition: ts_cache.h:45
FmgrInfo prsheadline
Definition: ts_cache.h:48
FmgrInfo prsend
Definition: ts_cache.h:47
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
#define MAXTOKENTYPE
Definition: ts_cache.c:60
static TSDictionaryCacheEntry * lastUsedDictionary
Definition: ts_cache.c:68
bool check_default_text_search_config(char **newval, void **extra, GucSource source)
Definition: ts_cache.c:602
Oid getTSCurrentConfig(bool emitError)
Definition: ts_cache.c:556
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:94
TSConfigCacheEntry * lookup_ts_config_cache(Oid cfgId)
Definition: ts_cache.c:385
static void init_ts_config_cache(void)
Definition: ts_cache.c:362
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
Definition: ts_cache.c:113
static HTAB * TSDictionaryCacheHash
Definition: ts_cache.c:67
static HTAB * TSConfigCacheHash
Definition: ts_cache.c:70
static TSParserCacheEntry * lastUsedParser
Definition: ts_cache.c:65
char * TSCurrentConfig
Definition: ts_cache.c:76
static Oid TSCurrentConfigCache
Definition: ts_cache.c:78
void assign_default_text_search_config(const char *newval, void *extra)
Definition: ts_cache.c:670
#define MAXDICTSPERTT
Definition: ts_cache.c:61
TSDictionaryCacheEntry * lookup_ts_dictionary_cache(Oid dictId)
Definition: ts_cache.c:208
static TSConfigCacheEntry * lastUsedConfig
Definition: ts_cache.c:71
static HTAB * TSParserCacheHash
Definition: ts_cache.c:64
struct TSDictionaryCacheEntry TSDictionaryCacheEntry
struct TSParserCacheEntry TSParserCacheEntry
List * deserialize_deflist(Datum txt)
Definition: tsearchcmds.c:1621
bool IsTransactionState(void)
Definition: xact.c:387