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-2024, 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"
34 #include "catalog/pg_ts_config.h"
36 #include "catalog/pg_ts_dict.h"
37 #include "catalog/pg_ts_parser.h"
38 #include "catalog/pg_ts_template.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 
64 static HTAB *TSParserCacheHash = NULL;
66 
67 static HTAB *TSDictionaryCacheHash = NULL;
69 
70 static HTAB *TSConfigCacheHash = NULL;
72 
73 /*
74  * GUC default_text_search_config, and a cache of the current config's OID
75  */
76 char *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  */
93 static void
94 InvalidateTSCacheCallBack(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,
125  &ctl, HASH_ELEM | HASH_BLOBS);
126  /* Flush cache on pg_ts_parser changes */
129 
130  /* Also make sure CacheMemoryContext exists */
131  if (!CacheMemoryContext)
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;
151  Form_pg_ts_parser prs;
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 
191  fmgr_info_cxt(entry->endOid, &entry->prsend, CacheMemoryContext);
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 {
210  TSDictionaryCacheEntry *entry;
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,
220  &ctl, HASH_ELEM | HASH_BLOBS);
221  /* Flush cache on pg_ts_dict and pg_ts_template changes */
226 
227  /* Also make sure CacheMemoryContext exists */
228  if (!CacheMemoryContext)
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  */
361 static void
363 {
364  HASHCTL ctl;
365 
366  ctl.keysize = sizeof(Oid);
367  ctl.entrysize = sizeof(TSConfigCacheEntry);
368  TSConfigCacheHash = hash_create("Tsearch configuration cache", 16,
369  &ctl, HASH_ELEM | HASH_BLOBS);
370  /* Flush cache on pg_ts_config and pg_ts_config_map changes */
375 
376  /* Also make sure CacheMemoryContext exists */
377  if (!CacheMemoryContext)
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;
411  Form_pg_ts_config cfg;
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 
519  systable_endscan_ordered(mapscan);
520  index_close(mapidx, AccessShareLock);
521  table_close(maprel, AccessShareLock);
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 
555 Oid
556 getTSCurrentConfig(bool emitError)
557 {
558  List *namelist;
559 
560  /* if we have a cached value, return it */
562  return TSCurrentConfigCache;
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  {
582  namelist = stringToQualifiedNameList(TSCurrentConfig, NULL);
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 
597  return TSCurrentConfigCache;
598 }
599 
600 /* GUC check_hook for default_text_search_config */
601 bool
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;
615  Form_pg_ts_config cfg;
616  char *buf;
617 
618  namelist = stringToQualifiedNameList(*newval,
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  {
633  ereport(NOTICE,
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 */
658  guc_free(*newval);
659  *newval = guc_strdup(LOG, buf);
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 */
669 void
670 assign_default_text_search_config(const char *newval, void *extra)
671 {
672  /* Just reset the cache to force a lookup on first use */
674 }
#define NameStr(name)
Definition: c.h:733
unsigned int uint32
Definition: c.h:493
#define MemSet(start, val, len)
Definition: c.h:1007
#define OidIsValid(objectId)
Definition: c.h:762
void CreateCacheMemoryContext(void)
Definition: catcache.c:666
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1395
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define LOG
Definition: elog.h:31
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#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:680
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:643
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:735
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:710
Oid MyDatabaseId
Definition: globals.c:91
void guc_free(void *ptr)
Definition: guc.c:691
#define newval
char * guc_strdup(int elevel, const char *src)
Definition: guc.c:679
GucSource
Definition: guc.h:108
@ PGC_S_TEST
Definition: guc.h:121
@ 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
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
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:1516
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
#define AccessShareLock
Definition: lockdefs.h:36
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3322
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:371
void pfree(void *pointer)
Definition: mcxt.c:1508
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1168
MemoryContext CacheMemoryContext
Definition: mcxt.c:140
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:600
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:163
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:101
Oid get_ts_config_oid(List *names, bool missing_ok)
Definition: namespace.c:3137
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:73
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:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static unsigned hash(unsigned *uv, int n)
Definition: rege_dfa.c:715
List * stringToQualifiedNameList(const char *string, Node *escontext)
Definition: regproc.c:1777
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:12071
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
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
Definition: dynahash.c:220
Oid * dictIds
Definition: ts_cache.h:68
Definition: pg_list.h:54
Definition: nodes.h:129
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:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479
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
TSDictionaryCacheEntry * lookup_ts_dictionary_cache(Oid dictId)
Definition: ts_cache.c:208
static void InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
Definition: ts_cache.c:94
static void init_ts_config_cache(void)
Definition: ts_cache.c:362
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
TSConfigCacheEntry * lookup_ts_config_cache(Oid cfgId)
Definition: ts_cache.c:385
TSParserCacheEntry * lookup_ts_parser_cache(Oid prsId)
Definition: ts_cache.c:113
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:379